v0.19.8.0
This commit is contained in:
@@ -399,12 +399,9 @@ namespace Barotrauma
|
||||
progressBar.Draw(spriteBatch, cam);
|
||||
}
|
||||
|
||||
void DrawInteractionIcon(Entity entity, string iconStyle)
|
||||
void DrawInteractionIcon(Entity entity, Identifier iconStyle)
|
||||
{
|
||||
if (entity == null || entity.Removed) { return; }
|
||||
var characterEntity = entity as Character;
|
||||
if (characterEntity is not null && (characterEntity.IsDead || characterEntity.IsIncapacitated)) { return; }
|
||||
if (GUIStyle.GetComponentStyle(iconStyle) is not GUIComponentStyle style) { return; }
|
||||
|
||||
Hull currentHull = entity switch
|
||||
{
|
||||
@@ -412,20 +409,28 @@ namespace Barotrauma
|
||||
Item item => item.CurrentHull,
|
||||
_ => null
|
||||
};
|
||||
|
||||
Range<float> visibleRange = new Range<float>(currentHull == Character.Controlled.CurrentHull ? 500.0f : 100.0f, float.PositiveInfinity);
|
||||
if (characterEntity?.CampaignInteractionType == CampaignMode.InteractionType.Examine)
|
||||
LocalizedString label = null;
|
||||
if (entity is Character characterEntity)
|
||||
{
|
||||
//TODO: we could probably do better than just hardcoding
|
||||
//a check for InteractionType.Examine here.
|
||||
if (characterEntity.IsDead || characterEntity.IsIncapacitated) { return; }
|
||||
if (characterEntity?.CampaignInteractionType == CampaignMode.InteractionType.Examine)
|
||||
{
|
||||
//TODO: we could probably do better than just hardcoding
|
||||
//a check for InteractionType.Examine here.
|
||||
|
||||
if (Vector2.DistanceSquared(character.Position, entity.Position) > 500f * 500f) { return; }
|
||||
if (Vector2.DistanceSquared(character.Position, entity.Position) > 500f * 500f) { return; }
|
||||
|
||||
var body = Submarine.CheckVisibility(character.SimPosition, entity.SimPosition, ignoreLevel: true);
|
||||
if (body != null && body.UserData != entity) { return; }
|
||||
var body = Submarine.CheckVisibility(character.SimPosition, entity.SimPosition, ignoreLevel: true);
|
||||
if (body != null && body.UserData != entity) { return; }
|
||||
|
||||
visibleRange = new Range<float>(-100f, 500f);
|
||||
visibleRange = new Range<float>(-100f, 500f);
|
||||
}
|
||||
label = characterEntity?.Info?.Title;
|
||||
}
|
||||
|
||||
if (GUIStyle.GetComponentStyle(iconStyle) is not GUIComponentStyle style) { return; }
|
||||
|
||||
float dist = Vector2.Distance(character.WorldPosition, entity.WorldPosition);
|
||||
float distFactor = 1.0f - MathUtils.InverseLerp(1000.0f, 3000.0f, dist);
|
||||
float alpha = MathHelper.Lerp(0.3f, 1.0f, distFactor);
|
||||
@@ -436,13 +441,13 @@ namespace Barotrauma
|
||||
visibleRange,
|
||||
style.GetDefaultSprite(),
|
||||
style.Color * alpha,
|
||||
label: characterEntity?.Info?.Title);
|
||||
label: label);
|
||||
}
|
||||
|
||||
foreach (Character npc in Character.CharacterList)
|
||||
{
|
||||
if (npc.CampaignInteractionType == CampaignMode.InteractionType.None) { continue; }
|
||||
DrawInteractionIcon(npc, "CampaignInteractionIcon." + npc.CampaignInteractionType);
|
||||
DrawInteractionIcon(npc, ("CampaignInteractionIcon." + npc.CampaignInteractionType).ToIdentifier());
|
||||
}
|
||||
|
||||
if (GameMain.GameSession?.GameMode is TutorialMode tutorialMode && tutorialMode.Tutorial is not null)
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using Barotrauma.Networking;
|
||||
using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
using System.Collections.Immutable;
|
||||
using System.Linq;
|
||||
|
||||
namespace Barotrauma
|
||||
@@ -141,7 +142,7 @@ namespace Barotrauma
|
||||
|
||||
public virtual void ClientEventWrite(IWriteMessage msg, NetEntityEvent.IData extraData = null)
|
||||
{
|
||||
if (!(extraData is IEventData eventData)) { throw new Exception($"Malformed character event: expected {nameof(Character)}.{nameof(IEventData)}"); }
|
||||
if (extraData is not IEventData eventData) { throw new Exception($"Malformed character event: expected {nameof(Character)}.{nameof(IEventData)}"); }
|
||||
|
||||
msg.WriteRangedInteger((int)eventData.EventType, (int)EventType.MinValue, (int)EventType.MaxValue);
|
||||
switch (eventData)
|
||||
@@ -471,25 +472,11 @@ namespace Barotrauma
|
||||
break;
|
||||
case EventType.AddToCrew:
|
||||
GameMain.GameSession.CrewManager.AddCharacter(this);
|
||||
CharacterTeamType teamID = (CharacterTeamType)msg.ReadByte();
|
||||
ushort itemCount = msg.ReadUInt16();
|
||||
for (int i = 0; i < itemCount; i++)
|
||||
{
|
||||
ushort itemID = msg.ReadUInt16();
|
||||
if (!(Entity.FindEntityByID(itemID) is Item item)) { continue; }
|
||||
item.AllowStealing = true;
|
||||
var wifiComponent = item.GetComponent<WifiComponent>();
|
||||
if (wifiComponent != null)
|
||||
{
|
||||
wifiComponent.TeamID = teamID;
|
||||
}
|
||||
var idCard = item.GetComponent<IdCard>();
|
||||
if (idCard != null)
|
||||
{
|
||||
idCard.TeamID = teamID;
|
||||
idCard.SubmarineSpecificID = 0;
|
||||
}
|
||||
}
|
||||
ReadItemTeamChange(msg, true);
|
||||
break;
|
||||
case EventType.RemoveFromCrew:
|
||||
GameMain.GameSession.CrewManager.RemoveCharacter(this, removeInfo: true);
|
||||
ReadItemTeamChange(msg, false);
|
||||
break;
|
||||
case EventType.UpdateExperience:
|
||||
int experienceAmount = msg.ReadInt32();
|
||||
@@ -520,9 +507,27 @@ namespace Barotrauma
|
||||
info?.ChangeSavedStatValue(statType, statValue, statIdentifier, removeOnDeath, setValue: true);
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
msg.ReadPadBits();
|
||||
|
||||
static void ReadItemTeamChange(IReadMessage msg, bool allowStealing)
|
||||
{
|
||||
var itemTeamChange = INetSerializableStruct.Read<ItemTeamChange>(msg);
|
||||
foreach (var itemID in itemTeamChange.ItemIds)
|
||||
{
|
||||
if (FindEntityByID(itemID) is not Item item) { continue; }
|
||||
item.AllowStealing = allowStealing;
|
||||
if (item.GetComponent<WifiComponent>() is { } wifiComponent)
|
||||
{
|
||||
wifiComponent.TeamID = itemTeamChange.TeamId;
|
||||
}
|
||||
if (item.GetComponent<IdCard>() is { } idCard)
|
||||
{
|
||||
idCard.TeamID = itemTeamChange.TeamId;
|
||||
idCard.SubmarineSpecificID = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static Character ReadSpawnData(IReadMessage inc)
|
||||
|
||||
@@ -280,6 +280,7 @@ namespace Barotrauma
|
||||
|
||||
cprButton = new GUIButton(new RectTransform(new Vector2(0.17f, 0.17f), characterIndicatorArea.RectTransform, Anchor.BottomLeft, scaleBasis: ScaleBasis.Smallest), text: "", style: "CPRButton")
|
||||
{
|
||||
UserData = UIHighlightAction.ElementId.CPRButton,
|
||||
OnClicked = (button, userData) =>
|
||||
{
|
||||
Character selectedCharacter = Character.Controlled?.SelectedCharacter;
|
||||
@@ -690,7 +691,7 @@ namespace Barotrauma
|
||||
{
|
||||
distortTimer = (distortTimer + deltaTime * distortSpeed) % MathHelper.TwoPi;
|
||||
Character.BlurStrength = (float)(Math.Sin(distortTimer) + 1.5f) * 0.25f * blurStrength;
|
||||
Character.DistortStrength = (float)(Math.Sin(distortTimer) + 1.0f) * 0.1f * distortStrength;
|
||||
Character.DistortStrength = (float)(Math.Sin(distortTimer) + 1.0f) * 0.05f * distortStrength;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1294,6 +1295,7 @@ namespace Barotrauma
|
||||
Dictionary<Identifier, float> treatmentSuitability = new Dictionary<Identifier, float>();
|
||||
GetSuitableTreatments(treatmentSuitability,
|
||||
normalize: true,
|
||||
user: Character.Controlled,
|
||||
ignoreHiddenAfflictions: true,
|
||||
limb: selectedLimbIndex == -1 ? null : Character.AnimController.Limbs.Find(l => l.HealthIndex == selectedLimbIndex));
|
||||
|
||||
@@ -1343,7 +1345,7 @@ namespace Barotrauma
|
||||
PlaySoundOnSelect = false,
|
||||
OnClicked = (btn, userdata) =>
|
||||
{
|
||||
if (!(userdata is ItemPrefab itemPrefab)) { return false; }
|
||||
if (userdata is not ItemPrefab itemPrefab) { return false; }
|
||||
var item = Character.Controlled.Inventory.FindItem(it => it.Prefab == itemPrefab, recursive: true);
|
||||
if (item == null) { return false; }
|
||||
Limb targetLimb = Character.AnimController.Limbs.FirstOrDefault(l => l.HealthIndex == selectedLimbIndex);
|
||||
@@ -1900,6 +1902,7 @@ namespace Barotrauma
|
||||
public void ClientRead(IReadMessage inc)
|
||||
{
|
||||
newAfflictions.Clear();
|
||||
newPeriodicEffects.Clear();
|
||||
byte afflictionCount = inc.ReadByte();
|
||||
for (int i = 0; i < afflictionCount; i++)
|
||||
{
|
||||
@@ -1921,7 +1924,7 @@ namespace Barotrauma
|
||||
int periodicAfflictionCount = inc.ReadByte();
|
||||
for (int j = 0; j < periodicAfflictionCount; j++)
|
||||
{
|
||||
float periodicAfflictionTimer = inc.ReadRangedSingle(afflictionPrefab.PeriodicEffects[j].MinInterval, afflictionPrefab.PeriodicEffects[j].MaxInterval, 8);
|
||||
float periodicAfflictionTimer = inc.ReadRangedSingle(0, afflictionPrefab.PeriodicEffects[j].MaxInterval, 8);
|
||||
newPeriodicEffects.Add((afflictionPrefab.PeriodicEffects[j], periodicAfflictionTimer));
|
||||
}
|
||||
newAfflictions.Add((null, afflictionPrefab, afflictionStrength));
|
||||
@@ -1991,13 +1994,13 @@ namespace Barotrauma
|
||||
//timer has wrapped around, apply the effect
|
||||
if (periodicEffect.timer - existingAffliction.PeriodicEffectTimers[periodicEffect.effect] > periodicEffect.effect.MinInterval / 2)
|
||||
{
|
||||
existingAffliction.PeriodicEffectTimers[periodicEffect.effect] = periodicEffect.timer;
|
||||
foreach (StatusEffect effect in periodicEffect.effect.StatusEffects)
|
||||
{
|
||||
Limb targetLimb = Character.AnimController.Limbs.FirstOrDefault(l => l.HealthIndex == limbHealths.IndexOf(limb));
|
||||
existingAffliction.ApplyStatusEffect(ActionType.OnActive, effect, deltaTime: 1.0f, this, targetLimb: targetLimb);
|
||||
}
|
||||
}
|
||||
existingAffliction.PeriodicEffectTimers[periodicEffect.effect] = periodicEffect.timer;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -92,11 +92,13 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
float prevSize = conversationList.TotalSize;
|
||||
|
||||
List<GUIButton> extraButtons = CreateConversation(conversationList, text, speaker, options, string.IsNullOrWhiteSpace(spriteIdentifier));
|
||||
AssignActionsToButtons(extraButtons, lastMessageBox);
|
||||
RecalculateLastMessage(conversationList, true);
|
||||
|
||||
conversationList.ScrollToEnd(0.5f);
|
||||
conversationList.BarScroll = (prevSize - conversationList.Content.Rect.Height) / (conversationList.TotalSize - conversationList.Content.Rect.Height);
|
||||
conversationList.ScrollToEnd(duration: 0.5f);
|
||||
lastMessageBox.SetBackgroundIcon(eventSprite);
|
||||
return;
|
||||
}
|
||||
@@ -112,7 +114,7 @@ namespace Barotrauma
|
||||
};
|
||||
messageBox.OnAddedToGUIUpdateList += (GUIComponent component) =>
|
||||
{
|
||||
if (!(Screen.Selected is GameScreen)) { messageBox.Close(); }
|
||||
if (Screen.Selected is not GameScreen) { messageBox.Close(); }
|
||||
};
|
||||
lastMessageBox = messageBox;
|
||||
|
||||
@@ -321,7 +323,7 @@ namespace Barotrauma
|
||||
AlwaysOverrideCursor = true
|
||||
};
|
||||
|
||||
LocalizedString translatedText = TextManager.Get(text).Fallback(text);
|
||||
LocalizedString translatedText = TextManager.ParseInputTypes(TextManager.Get(text)).Fallback(text);
|
||||
|
||||
if (speaker?.Info != null && drawChathead)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using System.Linq;
|
||||
|
||||
namespace Barotrauma;
|
||||
|
||||
partial class InventoryHighlightAction : EventAction
|
||||
{
|
||||
private static readonly Color highlightColor = Color.Orange;
|
||||
|
||||
partial void UpdateProjSpecific()
|
||||
{
|
||||
foreach (var target in ParentEvent.GetTargets(TargetTag))
|
||||
{
|
||||
SetHighlight(target);
|
||||
}
|
||||
}
|
||||
|
||||
private void SetHighlight(Entity entity)
|
||||
{
|
||||
if (entity is Item item)
|
||||
{
|
||||
int i = 0;
|
||||
foreach (var itemContainer in item.GetComponents<Items.Components.ItemContainer>())
|
||||
{
|
||||
if (ItemContainerIndex == -1 || i == ItemContainerIndex)
|
||||
{
|
||||
SetHighlight(itemContainer.Inventory);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
else if (entity is Character c)
|
||||
{
|
||||
SetHighlight(c.Inventory);
|
||||
}
|
||||
}
|
||||
|
||||
private void SetHighlight(Inventory inventory)
|
||||
{
|
||||
if (inventory?.visualSlots == null) { return; }
|
||||
for (int i = 0; i < inventory.visualSlots.Length; i++)
|
||||
{
|
||||
if (inventory.visualSlots[i].HighlightTimer > 0) { continue; }
|
||||
Item item = inventory.GetItemAt(i);
|
||||
if (IsSuitableItem(item) ||
|
||||
(Recursive && item?.OwnInventory != null && item.OwnInventory.FindAllItems(it => IsSuitableItem(it), recursive: true).Any()))
|
||||
{
|
||||
inventory.visualSlots[i].ShowBorderHighlight(highlightColor, 0.5f, 0.5f, 0.1f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool IsSuitableItem(Item item)
|
||||
{
|
||||
return (ItemIdentifier.IsEmpty && item == null) ||
|
||||
(item != null && (item.Prefab.Identifier == ItemIdentifier || item.HasTag(ItemIdentifier)));
|
||||
}
|
||||
}
|
||||
@@ -8,20 +8,24 @@ partial class MessageBoxAction : EventAction
|
||||
{
|
||||
partial void UpdateProjSpecific()
|
||||
{
|
||||
if (Type == ActionType.Create)
|
||||
if (Type == ActionType.Create || Type == ActionType.ConnectObjective)
|
||||
{
|
||||
CreateMessageBox();
|
||||
if (!ObjectiveTag.IsEmpty && GameMain.GameSession?.GameMode is TutorialMode tutorialMode)
|
||||
{
|
||||
Identifier id = Identifier.IsEmpty ? Text : Identifier;
|
||||
Identifier id = Identifier.IfEmpty(Text);
|
||||
var segment = Tutorial.Segment.CreateMessageBoxSegment(id, ObjectiveTag, CreateMessageBox);
|
||||
tutorialMode.Tutorial?.TriggerTutorialSegment(segment);
|
||||
tutorialMode.Tutorial?.TriggerTutorialSegment(segment, connectObjective: Type == ActionType.ConnectObjective);
|
||||
}
|
||||
}
|
||||
else if (Type == ActionType.Close)
|
||||
{
|
||||
GUIMessageBox.Close(Tag);
|
||||
}
|
||||
else if (Type == ActionType.Clear)
|
||||
{
|
||||
GUIMessageBox.CloseAll();
|
||||
}
|
||||
}
|
||||
|
||||
public void CreateMessageBox()
|
||||
|
||||
@@ -4,7 +4,7 @@ namespace Barotrauma;
|
||||
|
||||
partial class TutorialHighlightAction : EventAction
|
||||
{
|
||||
private static readonly Color highlightColor = Color.OrangeRed;
|
||||
private static readonly Color highlightColor = Color.Orange;
|
||||
|
||||
partial void UpdateProjSpecific()
|
||||
{
|
||||
@@ -19,32 +19,32 @@ partial class TutorialHighlightAction : EventAction
|
||||
{
|
||||
if (entity is Item i)
|
||||
{
|
||||
SetHighlight(i);
|
||||
SetItemHighlight(i);
|
||||
}
|
||||
else if (entity is Structure s)
|
||||
{
|
||||
SetHighlight(s);
|
||||
SetStructureHighlight(s);
|
||||
}
|
||||
else if (entity is Character c)
|
||||
{
|
||||
SetHighlight(c);
|
||||
SetCharacterHighlight(c);
|
||||
}
|
||||
}
|
||||
|
||||
private void SetHighlight(Item item)
|
||||
private void SetItemHighlight(Item item)
|
||||
{
|
||||
if (item.ExternalHighlight == State) { return; }
|
||||
item.SpriteColor = (State) ? highlightColor : Color.White;
|
||||
item.HighlightColor = State ? highlightColor : null;
|
||||
item.ExternalHighlight = State;
|
||||
}
|
||||
|
||||
private void SetHighlight(Structure structure)
|
||||
private void SetStructureHighlight(Structure structure)
|
||||
{
|
||||
structure.SpriteColor = (State) ? highlightColor : Color.White;
|
||||
structure.SpriteColor = State ? highlightColor : Color.White;
|
||||
structure.ExternalHighlight = State;
|
||||
}
|
||||
|
||||
private void SetHighlight(Character character)
|
||||
private void SetCharacterHighlight(Character character)
|
||||
{
|
||||
character.ExternalHighlight = State;
|
||||
}
|
||||
|
||||
@@ -11,13 +11,13 @@ partial class TutorialSegmentAction : EventAction
|
||||
// Only need to create the segment when it's being triggered (otherwise the tutorial already has the segment instance)
|
||||
if (Type == SegmentActionType.Trigger)
|
||||
{
|
||||
segment = Tutorial.Segment.CreateInfoBoxSegment(Id, ObjectiveTag, AutoPlayVideo ? Tutorials.AutoPlayVideo.Yes : Tutorials.AutoPlayVideo.No,
|
||||
segment = Tutorial.Segment.CreateInfoBoxSegment(Identifier, ObjectiveTag, AutoPlayVideo ? Tutorials.AutoPlayVideo.Yes : Tutorials.AutoPlayVideo.No,
|
||||
new Tutorial.Segment.Text(TextTag, Width, Height, Anchor.Center),
|
||||
new Tutorial.Segment.Video(VideoFile, TextTag, Width, Height));
|
||||
}
|
||||
else if (Type == SegmentActionType.Add)
|
||||
{
|
||||
segment = Tutorial.Segment.CreateObjectiveSegment(Id, !ObjectiveTag.IsEmpty ? ObjectiveTag : Id);
|
||||
segment = Tutorial.Segment.CreateObjectiveSegment(Identifier, !ObjectiveTag.IsEmpty ? ObjectiveTag : Identifier);
|
||||
}
|
||||
if (GameMain.GameSession?.GameMode is TutorialMode tutorialMode)
|
||||
{
|
||||
@@ -30,21 +30,21 @@ partial class TutorialSegmentAction : EventAction
|
||||
tutorial.TriggerTutorialSegment(segment);
|
||||
break;
|
||||
case SegmentActionType.Complete:
|
||||
tutorial.CompleteTutorialSegment(Id);
|
||||
tutorial.CompleteTutorialSegment(Identifier);
|
||||
break;
|
||||
case SegmentActionType.Remove:
|
||||
tutorial.RemoveTutorialSegment(Id);
|
||||
tutorial.RemoveTutorialSegment(Identifier);
|
||||
break;
|
||||
case SegmentActionType.CompleteAndRemove:
|
||||
tutorial.CompleteTutorialSegment(Id);
|
||||
tutorial.RemoveTutorialSegment(Id);
|
||||
tutorial.CompleteTutorialSegment(Identifier);
|
||||
tutorial.RemoveTutorialSegment(Identifier);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DebugConsole.ShowError($"Error in event \"{ParentEvent.Prefab.Identifier}\": attempting to use TutorialSegmentAction during a non-Tutorial game mode!");
|
||||
DebugConsole.ThrowError($"Error in event \"{ParentEvent.Prefab.Identifier}\": attempting to use TutorialSegmentAction during a non-Tutorial game mode!");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using System.Linq;
|
||||
|
||||
namespace Barotrauma;
|
||||
|
||||
partial class UIHighlightAction : EventAction
|
||||
{
|
||||
private static readonly Color highlightColor = Color.Orange;
|
||||
|
||||
partial void UpdateProjSpecific()
|
||||
{
|
||||
bool useCircularFlash = false;
|
||||
GUIComponent component = null;
|
||||
|
||||
if (Id != ElementId.None)
|
||||
{
|
||||
component = GUI.GetAdditions().FirstOrDefault(c => Equals(Id, c.UserData));
|
||||
}
|
||||
else if (!EntityIdentifier.IsEmpty)
|
||||
{
|
||||
component = GUI.GetAdditions().FirstOrDefault(c =>
|
||||
c.UserData is MapEntityPrefab mep && mep.Identifier == EntityIdentifier || c.UserData is MapEntity me && me.Prefab.Identifier == EntityIdentifier);
|
||||
}
|
||||
else if (!OrderIdentifier.IsEmpty)
|
||||
{
|
||||
useCircularFlash = true;
|
||||
if (!OrderTargetTag.IsEmpty)
|
||||
{
|
||||
component =
|
||||
GUI.GetAdditions().FirstOrDefault(c =>
|
||||
c.UserData is CrewManager.MinimapNodeData nodeData && nodeData.Order is Order order &&
|
||||
order.Identifier == OrderIdentifier && order.Option == OrderOption && order.TargetEntity is Item item && item.HasTag(OrderTargetTag));
|
||||
}
|
||||
component ??=
|
||||
GUI.GetAdditions().FirstOrDefault(c => c.UserData is Order order && order.Identifier == OrderIdentifier && order.Option == OrderOption) ??
|
||||
GUI.GetAdditions().FirstOrDefault(c => c.UserData is Order order && order.Identifier == OrderIdentifier) ??
|
||||
GUI.GetAdditions().FirstOrDefault(c => Equals(OrderCategory, c.UserData));
|
||||
}
|
||||
|
||||
if (component != null && component.FlashTimer <= 0.0f)
|
||||
{
|
||||
component.Flash(highlightColor, useCircularFlash: useCircularFlash);
|
||||
component.Bounce |= Bounce;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -651,11 +651,11 @@ namespace Barotrauma
|
||||
break;
|
||||
case NetworkEventType.MISSION:
|
||||
Identifier missionIdentifier = msg.ReadIdentifier();
|
||||
|
||||
string missionName = msg.ReadString();
|
||||
MissionPrefab? prefab = MissionPrefab.Prefabs.Find(mp => mp.Identifier == missionIdentifier);
|
||||
if (prefab != null)
|
||||
{
|
||||
new GUIMessageBox(string.Empty, TextManager.GetWithVariable("missionunlocked", "[missionname]", prefab.Name),
|
||||
new GUIMessageBox(string.Empty, TextManager.GetWithVariable("missionunlocked", "[missionname]", missionName),
|
||||
Array.Empty<LocalizedString>(), type: GUIMessageBox.Type.InGame, icon: prefab.Icon, relativeSize: new Vector2(0.3f, 0.15f), minSize: new Point(512, 128))
|
||||
{
|
||||
IconColor = prefab.IconColor
|
||||
|
||||
@@ -410,7 +410,7 @@ namespace Barotrauma
|
||||
{
|
||||
y += yStep;
|
||||
DrawString(spriteBatch, new Vector2(10, y),
|
||||
"Sub pos: " + Submarine.MainSub.Position.ToPoint(),
|
||||
"Sub pos: " + Submarine.MainSub.WorldPosition.ToPoint(),
|
||||
Color.White, Color.Black * 0.5f, 0, GUIStyle.SmallFont);
|
||||
}
|
||||
|
||||
@@ -879,6 +879,11 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static IEnumerable<GUIComponent> GetAdditions()
|
||||
{
|
||||
return additions;
|
||||
}
|
||||
#endregion
|
||||
|
||||
public static GUIComponent MouseOn { get; private set; }
|
||||
|
||||
@@ -486,7 +486,7 @@ namespace Barotrauma
|
||||
{
|
||||
if (bounceTimer > 3.0f || bounceDown)
|
||||
{
|
||||
RectTransform.ScreenSpaceOffset = new Point(RectTransform.ScreenSpaceOffset.X, (int) -(bounceJump * 10f));
|
||||
RectTransform.ScreenSpaceOffset = new Point(RectTransform.ScreenSpaceOffset.X, (int) -(bounceJump * 15f * GUI.Scale));
|
||||
if (!bounceDown)
|
||||
{
|
||||
bounceJump += deltaTime * 4;
|
||||
@@ -503,6 +503,7 @@ namespace Barotrauma
|
||||
bounceJump = 0.0f;
|
||||
bounceTimer = 0.0f;
|
||||
bounceDown = false;
|
||||
Bounce = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,11 +85,11 @@ namespace Barotrauma
|
||||
get { return sprite; }
|
||||
set
|
||||
{
|
||||
if (sprite == value) return;
|
||||
if (sprite == value) { return; }
|
||||
sprite = value;
|
||||
sourceRect = value == null ? Rectangle.Empty : value.SourceRect;
|
||||
origin = value == null ? Vector2.Zero : value.size / 2;
|
||||
if (scaleToFit) RecalculateScale();
|
||||
if (scaleToFit) { RecalculateScale(); }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -601,16 +601,13 @@ namespace Barotrauma
|
||||
yield return CoroutineStatus.Success;
|
||||
}
|
||||
float t = 0.0f;
|
||||
float startScroll = BarScroll * BarSize;
|
||||
float startScroll = BarScroll;
|
||||
float distanceToTravel = ScrollBar.MaxValue - startScroll;
|
||||
float progress = startScroll;
|
||||
float speed = distanceToTravel / duration;
|
||||
|
||||
while (t < duration && !MathUtils.NearlyEqual(ScrollBar.MaxValue, progress))
|
||||
while (t < duration && !MathUtils.NearlyEqual(ScrollBar.MaxValue, BarScroll))
|
||||
{
|
||||
t += CoroutineManager.DeltaTime;
|
||||
progress += speed * CoroutineManager.DeltaTime;
|
||||
BarScroll = progress;
|
||||
BarScroll += speed * CoroutineManager.DeltaTime;
|
||||
yield return CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
|
||||
@@ -207,7 +207,7 @@ namespace Barotrauma
|
||||
{
|
||||
InnerFrame.RectTransform.AbsoluteOffset = new Point(0, GameMain.GraphicsHeight);
|
||||
CanBeFocused = false;
|
||||
AutoClose = true;
|
||||
AutoClose = type == Type.InGame;
|
||||
GUIStyle.Apply(InnerFrame, "", this);
|
||||
|
||||
var horizontalLayoutGroup = new GUILayoutGroup(new RectTransform(new Vector2(0.98f, 0.95f), InnerFrame.RectTransform, Anchor.Center),
|
||||
|
||||
@@ -160,8 +160,13 @@ namespace Barotrauma
|
||||
|
||||
public static Point ItemFrameOffset => new Point(0, 3).Multiply(GUI.SlicedSpriteScale);
|
||||
|
||||
public static GUIComponentStyle GetComponentStyle(string name)
|
||||
=> ComponentStyles.TryGet(name, out var style) ? style : null;
|
||||
public static GUIComponentStyle GetComponentStyle(string styleName)
|
||||
{
|
||||
return GetComponentStyle(styleName.ToIdentifier());
|
||||
}
|
||||
|
||||
public static GUIComponentStyle GetComponentStyle(Identifier identifier)
|
||||
=> ComponentStyles.TryGet(identifier, out var style) ? style : null;
|
||||
|
||||
public static void Apply(GUIComponent targetComponent, string styleName = "", GUIComponent parent = null)
|
||||
{
|
||||
|
||||
@@ -238,7 +238,7 @@ namespace Barotrauma
|
||||
errorId = "Store.SelectStore:StoreDoesntExist";
|
||||
msg = $"Error selecting store with identifier \"{identifier}\" at {CurrentLocation}: store with the identifier doesn't exist at the location.";
|
||||
}
|
||||
DebugConsole.ShowError(msg);
|
||||
DebugConsole.LogError(msg);
|
||||
GameAnalyticsManager.AddErrorEventOnce(errorId, GameAnalyticsManager.ErrorSeverity.Error, msg);
|
||||
}
|
||||
}
|
||||
@@ -263,7 +263,7 @@ namespace Barotrauma
|
||||
}
|
||||
if (!msg.IsNullOrEmpty())
|
||||
{
|
||||
DebugConsole.ShowError(msg);
|
||||
DebugConsole.LogError(msg);
|
||||
GameAnalyticsManager.AddErrorEventOnce(errorId, GameAnalyticsManager.ErrorSeverity.Error, msg);
|
||||
}
|
||||
}
|
||||
@@ -1250,7 +1250,7 @@ namespace Barotrauma
|
||||
}
|
||||
catch (NotImplementedException e)
|
||||
{
|
||||
DebugConsole.ShowError($"Error getting item price: Uknown store tab type. {e.StackTrace.CleanupStackTrace()}");
|
||||
DebugConsole.LogError($"Error getting item price: Uknown store tab type. {e.StackTrace.CleanupStackTrace()}");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1808,7 +1808,7 @@ namespace Barotrauma
|
||||
{
|
||||
string errorMsg = $"Error creating a store quantity label text: unknown store tab.\n{e.StackTrace.CleanupStackTrace()}";
|
||||
#if DEBUG
|
||||
DebugConsole.ShowError(errorMsg);
|
||||
DebugConsole.LogError(errorMsg);
|
||||
#else
|
||||
DebugConsole.AddWarning(errorMsg);
|
||||
#endif
|
||||
@@ -1882,7 +1882,7 @@ namespace Barotrauma
|
||||
}
|
||||
catch (NotImplementedException e)
|
||||
{
|
||||
DebugConsole.ShowError($"Error getting item availability: Uknown store tab type. {e.StackTrace.CleanupStackTrace()}");
|
||||
DebugConsole.LogError($"Error getting item availability: Uknown store tab type. {e.StackTrace.CleanupStackTrace()}");
|
||||
}
|
||||
if (list != null && list.Find(i => i.ItemPrefab == itemPrefab) is PurchasedItem item)
|
||||
{
|
||||
@@ -1962,7 +1962,7 @@ namespace Barotrauma
|
||||
}
|
||||
catch (NotImplementedException e)
|
||||
{
|
||||
DebugConsole.ShowError($"Error adding an item to the shopping crate: Uknown store tab type. {e.StackTrace.CleanupStackTrace()}");
|
||||
DebugConsole.LogError($"Error adding an item to the shopping crate: Uknown store tab type. {e.StackTrace.CleanupStackTrace()}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1982,7 +1982,7 @@ namespace Barotrauma
|
||||
}
|
||||
catch (NotImplementedException e)
|
||||
{
|
||||
DebugConsole.ShowError($"Error clearing the shopping crate: Uknown store tab type. {e.StackTrace.CleanupStackTrace()}");
|
||||
DebugConsole.LogError($"Error clearing the shopping crate: Uknown store tab type. {e.StackTrace.CleanupStackTrace()}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -2029,7 +2029,7 @@ namespace Barotrauma
|
||||
}
|
||||
catch (NotImplementedException e)
|
||||
{
|
||||
DebugConsole.ShowError($"Error confirming the store transaction: Uknown store tab type. {e.StackTrace.CleanupStackTrace()}");
|
||||
DebugConsole.LogError($"Error confirming the store transaction: Uknown store tab type. {e.StackTrace.CleanupStackTrace()}");
|
||||
return false;
|
||||
}
|
||||
var itemsToRemove = new List<PurchasedItem>();
|
||||
|
||||
@@ -206,9 +206,9 @@ namespace Barotrauma
|
||||
transferMenuButton.RectTransform.AbsoluteOffset = new Point(0, -pos - transferMenu.Rect.Height);
|
||||
}
|
||||
GameSession.UpdateTalentNotificationIndicator(talentPointNotification);
|
||||
if (Character.Controlled is { } controlled && talentResetButton != null && talentApplyButton != null)
|
||||
if (Character.Controlled?.Info is { } characterInfo && talentResetButton != null && talentApplyButton != null)
|
||||
{
|
||||
int talentCount = selectedTalents.Count - controlled.Info.GetUnlockedTalentsInTree().Count();
|
||||
int talentCount = selectedTalents.Count - characterInfo.GetUnlockedTalentsInTree().Count();
|
||||
talentResetButton.Enabled = talentApplyButton.Enabled = talentCount > 0;
|
||||
if (talentApplyButton.Enabled && talentApplyButton.FlashTimer <= 0.0f)
|
||||
{
|
||||
@@ -1918,14 +1918,18 @@ namespace Barotrauma
|
||||
skillListBox = new GUIListBox(new RectTransform(new Vector2(1f, 1f - skillBlock.RectTransform.RelativeSize.Y), skillLayout.RectTransform), style: null);
|
||||
CreateSkillList(controlledCharacter, info, skillListBox);
|
||||
|
||||
if (controlledCharacter != null)
|
||||
new GUIFrame(new RectTransform(new Vector2(1f, 1f), contentLayout.RectTransform), style: "HorizontalLine");
|
||||
|
||||
GUIListBox talentTreeListBox = new GUIListBox(new RectTransform(new Vector2(1f, 0.6f), contentLayout.RectTransform, Anchor.TopCenter), isHorizontal: true, style: null);
|
||||
|
||||
if (controlledCharacter == null)
|
||||
{
|
||||
talentTreeListBox.Enabled = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!TalentTree.JobTalentTrees.TryGet(info.Job.Prefab.Identifier, out TalentTree talentTree)) { return; }
|
||||
|
||||
new GUIFrame(new RectTransform(new Vector2(1f, 1f), contentLayout.RectTransform), style: "HorizontalLine");
|
||||
|
||||
GUIListBox talentTreeListBox = new GUIListBox(new RectTransform(new Vector2(1f, 0.6f), contentLayout.RectTransform, Anchor.TopCenter), isHorizontal: true, style: null);
|
||||
|
||||
selectedTalents = info.GetUnlockedTalentsInTree().ToList();
|
||||
|
||||
List<GUITextBlock> subTreeNames = new List<GUITextBlock>();
|
||||
|
||||
@@ -874,7 +874,7 @@ namespace Barotrauma
|
||||
itemPrefab.SwappableItem.CanBeBought &&
|
||||
itemPrefab.SwappableItem.SwapIdentifier.Equals(item.Prefab.SwappableItem.SwapIdentifier, StringComparison.OrdinalIgnoreCase)).Cast<ItemPrefab>();
|
||||
|
||||
var linkedItems = Campaign.UpgradeManager.GetLinkedItemsToSwap(item) ?? new List<Item>() { item };
|
||||
var linkedItems = UpgradeManager.GetLinkedItemsToSwap(item) ?? new List<Item>() { item };
|
||||
//create the swap entry only for one of the items (the one with the smallest ID)
|
||||
if (linkedItems.Min(it => it.ID) < item.ID) { return; }
|
||||
|
||||
@@ -910,7 +910,7 @@ namespace Barotrauma
|
||||
GUILayoutGroup buttonLayout = new GUILayoutGroup(rectT(1f, 1f, toggleButton.Frame), isHorizontal: true);
|
||||
|
||||
LocalizedString slotText = "";
|
||||
if (linkedItems.Count > 1)
|
||||
if (linkedItems.Count() > 1)
|
||||
{
|
||||
slotText = TextManager.GetWithVariable("weaponslot", "[number]", string.Join(", ", linkedItems.Select(it => (swappableEntities.IndexOf(it) + 1).ToString())));
|
||||
}
|
||||
@@ -982,7 +982,7 @@ namespace Barotrauma
|
||||
|
||||
bool isPurchased = item.AvailableSwaps.Contains(replacement);
|
||||
|
||||
int price = isPurchased || replacement == item.Prefab ? 0 : replacement.SwappableItem.GetPrice(Campaign.Map?.CurrentLocation) * linkedItems.Count;
|
||||
int price = isPurchased || replacement == item.Prefab ? 0 : replacement.SwappableItem.GetPrice(Campaign.Map?.CurrentLocation) * linkedItems.Count();
|
||||
|
||||
frames.Add(CreateUpgradeEntry(rectT(1f, 0.25f, parent.Content), replacement.UpgradePreviewSprite, replacement.Name, replacement.Description,
|
||||
price, replacement,
|
||||
@@ -998,7 +998,7 @@ namespace Barotrauma
|
||||
{
|
||||
LocalizedString promptBody = TextManager.GetWithVariables(isPurchased ? "upgrades.itemswappromptbody" : "upgrades.purchaseitemswappromptbody",
|
||||
("[itemtoinstall]", replacement.Name),
|
||||
("[amount]", (replacement.SwappableItem.GetPrice(Campaign?.Map?.CurrentLocation) * linkedItems.Count).ToString()));
|
||||
("[amount]", (replacement.SwappableItem.GetPrice(Campaign?.Map?.CurrentLocation) * linkedItems.Count()).ToString()));
|
||||
currectConfirmation = EventEditorScreen.AskForConfirmation(TextManager.Get("Upgrades.PurchasePromptTitle"), promptBody, () =>
|
||||
{
|
||||
if (GameMain.NetworkMember != null)
|
||||
@@ -1042,7 +1042,7 @@ namespace Barotrauma
|
||||
}
|
||||
if (toggleButton.Selected)
|
||||
{
|
||||
var linkedItems = Campaign.UpgradeManager.GetLinkedItemsToSwap(item);
|
||||
var linkedItems = UpgradeManager.GetLinkedItemsToSwap(item);
|
||||
foreach (var itemPreview in itemPreviews)
|
||||
{
|
||||
itemPreview.Value.OutlineColor = itemPreview.Value.Color = linkedItems.Contains(itemPreview.Key) ? GUIStyle.Orange : previewWhite;
|
||||
@@ -1391,7 +1391,7 @@ namespace Barotrauma
|
||||
{
|
||||
if (selectedUpgradeCategoryLayout != null)
|
||||
{
|
||||
var linkedItems = HoveredEntity is Item hoveredItem ? Campaign.UpgradeManager.GetLinkedItemsToSwap(hoveredItem) : new List<Item>();
|
||||
var linkedItems = HoveredEntity is Item hoveredItem ? UpgradeManager.GetLinkedItemsToSwap(hoveredItem) : new List<Item>();
|
||||
if (selectedUpgradeCategoryLayout.FindChild(c => c.UserData is Item item && (item == HoveredEntity || linkedItems.Contains(item)), recursive: true) is GUIButton itemElement)
|
||||
{
|
||||
if (!itemElement.Selected) { itemElement.OnClicked(itemElement, itemElement.UserData); }
|
||||
|
||||
@@ -139,7 +139,7 @@ namespace Barotrauma
|
||||
}
|
||||
catch (NotImplementedException e)
|
||||
{
|
||||
DebugConsole.ShowError($"Error selling items: uknown store tab type \"{sellingMode}\".\n{e.StackTrace.CleanupStackTrace()}");
|
||||
DebugConsole.LogError($"Error selling items: uknown store tab type \"{sellingMode}\".\n{e.StackTrace.CleanupStackTrace()}");
|
||||
return;
|
||||
}
|
||||
bool canAddToRemoveQueue = campaign.IsSinglePlayer && Entity.Spawner != null;
|
||||
@@ -148,7 +148,7 @@ namespace Barotrauma
|
||||
var sellValues = GetSellValuesAtCurrentLocation(storeIdentifier, itemsToSell.Select(i => i.ItemPrefab));
|
||||
if (!(Location.GetStore(storeIdentifier) is { } store))
|
||||
{
|
||||
DebugConsole.ShowError($"Error selling items at {Location}: no store with identifier \"{storeIdentifier}\" exists.\n{Environment.StackTrace.CleanupStackTrace()}");
|
||||
DebugConsole.LogError($"Error selling items at {Location}: no store with identifier \"{storeIdentifier}\" exists.\n{Environment.StackTrace.CleanupStackTrace()}");
|
||||
return;
|
||||
}
|
||||
var storeSpecificSoldItems = GetSoldItems(storeIdentifier, create: true);
|
||||
|
||||
@@ -291,29 +291,13 @@ namespace Barotrauma
|
||||
return crewArea.Rect;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove the character from the crew (and crew menus).
|
||||
/// </summary>
|
||||
/// <param name="character">The character to remove</param>
|
||||
/// <param name="removeInfo">If the character info is also removed, the character will not be visible in the round summary.</param>
|
||||
public void RemoveCharacter(Character character, bool removeInfo = false, bool resetCrewListIndex = true)
|
||||
{
|
||||
if (character == null)
|
||||
{
|
||||
DebugConsole.ThrowError("Tried to remove a null character from CrewManager.\n" + Environment.StackTrace.CleanupStackTrace());
|
||||
return;
|
||||
}
|
||||
characters.Remove(character);
|
||||
if (removeInfo) { characterInfos.Remove(character.Info); }
|
||||
if (resetCrewListIndex) { ResetCrewListIndex(character); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add character to the list without actually adding it to the crew
|
||||
/// </summary>
|
||||
public GUIComponent AddCharacterToCrewList(Character character)
|
||||
{
|
||||
if (character == null) { return null; }
|
||||
if (crewList.Content.Children.Any(c => c.UserData as Character == character)) { return null; }
|
||||
|
||||
var background = new GUIFrame(
|
||||
new RectTransform(crewListEntrySize, parent: crewList.Content.RectTransform, anchor: Anchor.TopRight),
|
||||
@@ -509,7 +493,15 @@ namespace Barotrauma
|
||||
return background;
|
||||
}
|
||||
|
||||
private void SetCharacterComponentTooltip(GUIComponent characterComponent)
|
||||
public void RemoveCharacterFromCrewList(Character character)
|
||||
{
|
||||
if (crewList?.Content.GetChildByUserData(character) is { } component)
|
||||
{
|
||||
crewList.RemoveChild(component);
|
||||
}
|
||||
}
|
||||
|
||||
private static void SetCharacterComponentTooltip(GUIComponent characterComponent)
|
||||
{
|
||||
if (!(characterComponent?.UserData is Character character)) { return; }
|
||||
if (character.Info?.Job?.Prefab == null) { return; }
|
||||
@@ -2821,7 +2813,7 @@ namespace Barotrauma
|
||||
return node;
|
||||
}
|
||||
|
||||
private struct MinimapNodeData
|
||||
public struct MinimapNodeData
|
||||
{
|
||||
public Order Order;
|
||||
}
|
||||
|
||||
@@ -761,6 +761,7 @@ namespace Barotrauma
|
||||
item.PendingItemSwap = null;
|
||||
}
|
||||
}
|
||||
campaign.CampaignUI?.UpgradeStore?.RequestRefresh();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -78,7 +78,7 @@ namespace Barotrauma.Tutorials
|
||||
|
||||
public Action OnClickObjective;
|
||||
|
||||
public readonly TutorialSegmentType SegmentType;
|
||||
public TutorialSegmentType SegmentType { get; private set; }
|
||||
|
||||
public static Segment CreateInfoBoxSegment(Identifier id, Identifier objectiveTextTag, AutoPlayVideo autoPlayVideo, Text textContent = default, Video videoContent = default)
|
||||
{
|
||||
@@ -119,6 +119,12 @@ namespace Barotrauma.Tutorials
|
||||
ObjectiveText = TextManager.ParseInputTypes(TextManager.Get(objectiveTextTag));
|
||||
SegmentType = TutorialSegmentType.Objective;
|
||||
}
|
||||
|
||||
public void ConnectMessageBox(Segment messageBoxSegment)
|
||||
{
|
||||
SegmentType = TutorialSegmentType.MessageBox;
|
||||
OnClickObjective = messageBoxSegment.OnClickObjective;
|
||||
}
|
||||
}
|
||||
|
||||
private bool completed;
|
||||
@@ -144,6 +150,7 @@ namespace Barotrauma.Tutorials
|
||||
private readonly EventPrefab eventPrefab;
|
||||
|
||||
private CoroutineHandle tutorialCoroutine;
|
||||
private CoroutineHandle completedCoroutine;
|
||||
|
||||
private Character character;
|
||||
|
||||
@@ -154,7 +161,7 @@ namespace Barotrauma.Tutorials
|
||||
|
||||
private SubmarineInfo startOutpost = null;
|
||||
|
||||
public readonly List<(Entity entity, string iconStyle)> Icons = new List<(Entity entity, string iconStyle)>();
|
||||
public readonly List<(Entity entity, Identifier iconStyle)> Icons = new List<(Entity entity, Identifier iconStyle)>();
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -331,13 +338,16 @@ namespace Barotrauma.Tutorials
|
||||
{
|
||||
CoroutineManager.StopCoroutines(tutorialCoroutine);
|
||||
}
|
||||
GUI.PreventPauseMenuToggle = false;
|
||||
if (completedCoroutine == null && !CoroutineManager.IsCoroutineRunning(completedCoroutine))
|
||||
{
|
||||
GUI.PreventPauseMenuToggle = false;
|
||||
}
|
||||
ContentRunning = false;
|
||||
infoBox = null;
|
||||
}
|
||||
else if (Character.Controlled.IsDead)
|
||||
else
|
||||
{
|
||||
CoroutineManager.StartCoroutine(Dead());
|
||||
character = Character.Controlled;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -385,7 +395,7 @@ namespace Barotrauma.Tutorials
|
||||
|
||||
if (eventPrefab == null)
|
||||
{
|
||||
DebugConsole.ShowError($"No tutorial event defined for the tutorial (identifier: \"{TutorialPrefab?.Identifier.ToString() ?? "null"})\"");
|
||||
DebugConsole.LogError($"No tutorial event defined for the tutorial (identifier: \"{TutorialPrefab?.Identifier.ToString() ?? "null"})\"");
|
||||
yield return CoroutineStatus.Failure;
|
||||
}
|
||||
|
||||
@@ -399,7 +409,7 @@ namespace Barotrauma.Tutorials
|
||||
}
|
||||
else
|
||||
{
|
||||
DebugConsole.ShowError($"Failed to create an instance for a tutorial event (identifier: \"{eventPrefab.Identifier}\"");
|
||||
DebugConsole.LogError($"Failed to create an instance for a tutorial event (identifier: \"{eventPrefab.Identifier}\"");
|
||||
yield return CoroutineStatus.Failure;
|
||||
}
|
||||
|
||||
@@ -409,10 +419,12 @@ namespace Barotrauma.Tutorials
|
||||
public void Complete()
|
||||
{
|
||||
GameAnalyticsManager.AddDesignEvent($"Tutorial:{Identifier}:Completed");
|
||||
CoroutineManager.StartCoroutine(TutorialCompleted());
|
||||
completedCoroutine = CoroutineManager.StartCoroutine(TutorialCompleted());
|
||||
|
||||
IEnumerable<CoroutineStatus> TutorialCompleted()
|
||||
{
|
||||
while (GUI.PauseMenuOpen) { yield return CoroutineStatus.Running; }
|
||||
|
||||
GUI.PreventPauseMenuToggle = true;
|
||||
Character.Controlled.ClearInputs();
|
||||
Character.Controlled = null;
|
||||
@@ -423,7 +435,7 @@ namespace Barotrauma.Tutorials
|
||||
var endCinematic = new CameraTransition(Submarine.MainSub, GameMain.GameScreen.Cam, null, Alignment.Center, panDuration: FadeOutTime);
|
||||
Completed = true;
|
||||
|
||||
while (endCinematic.Running) { yield return null; }
|
||||
while (endCinematic.Running) { yield return CoroutineStatus.Running; }
|
||||
|
||||
Stop();
|
||||
GameMain.MainMenuScreen.ReturnToMainMenu(null, null);
|
||||
@@ -432,16 +444,18 @@ namespace Barotrauma.Tutorials
|
||||
|
||||
private bool Restart(GUIButton button, object obj)
|
||||
{
|
||||
GUI.PreventPauseMenuToggle = false;
|
||||
GUIMessageBox.MessageBoxes.Clear();
|
||||
GameMain.MainMenuScreen.ReturnToMainMenu(button, obj);
|
||||
Start();
|
||||
return true;
|
||||
}
|
||||
|
||||
public void TriggerTutorialSegment(Segment segment)
|
||||
public void TriggerTutorialSegment(Segment segment, bool connectObjective = false)
|
||||
{
|
||||
if (segment.SegmentType != TutorialSegmentType.InfoBox)
|
||||
{
|
||||
ActiveObjectives.Add(segment);
|
||||
AddToObjectiveList(segment);
|
||||
AddToObjectiveList(segment, connectObjective);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -488,11 +502,14 @@ namespace Barotrauma.Tutorials
|
||||
}
|
||||
if (GUIStyle.GetComponentStyle("ObjectiveIndicatorCompleted") is GUIComponentStyle style)
|
||||
{
|
||||
//return if already completed
|
||||
if (segment.ObjectiveStateIndicator.Style == style) { return; }
|
||||
segment.ObjectiveStateIndicator.ApplyStyle(style);
|
||||
}
|
||||
segment.ObjectiveStateIndicator.Parent.Flash(color: GUIStyle.Green, flashDuration: 0.35f, useRectangleFlash: true);
|
||||
segment.ObjectiveButton.OnClicked = null;
|
||||
segment.ObjectiveButton.CanBeFocused = false;
|
||||
GameAnalyticsManager.AddDesignEvent($"Tutorial:{Identifier}:{segmentId}:Completed");
|
||||
}
|
||||
|
||||
public void RemoveTutorialSegment(Identifier segmentId)
|
||||
@@ -568,8 +585,18 @@ namespace Barotrauma.Tutorials
|
||||
/// <summary>
|
||||
/// Adds the segment to the objective list
|
||||
/// </summary>
|
||||
private void AddToObjectiveList(Segment segment)
|
||||
private void AddToObjectiveList(Segment segment, bool connectExisting = false)
|
||||
{
|
||||
if (connectExisting)
|
||||
{
|
||||
if (ActiveObjectives.Find(o => o.Id == segment.Id) is { } existingSegment)
|
||||
{
|
||||
existingSegment.ConnectMessageBox(segment);
|
||||
SetButtonBehavior(existingSegment);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
var frameRt = new RectTransform(new Vector2(1.0f, 0.1f), objectiveGroup.RectTransform)
|
||||
{
|
||||
AbsoluteOffset = GetObjectiveHiddenPosition(),
|
||||
@@ -595,15 +622,25 @@ namespace Barotrauma.Tutorials
|
||||
frame.RectTransform.IsFixedSize = true;
|
||||
|
||||
var indicatorRt = new RectTransform(new Point(objectiveGroup.AbsoluteSpacing), frame.RectTransform, isFixedSize: true);
|
||||
segment.ObjectiveStateIndicator = new GUIImage(indicatorRt, "ObjectiveIndicatorIncomplete");;
|
||||
segment.ObjectiveStateIndicator = new GUIImage(indicatorRt, "ObjectiveIndicatorIncomplete");
|
||||
|
||||
SetTransparent(segment.LinkedTextBlock);
|
||||
|
||||
segment.ObjectiveButton = new GUIButton(new RectTransform(Vector2.One, segment.LinkedTextBlock.RectTransform, Anchor.TopLeft, Pivot.TopLeft), style: null)
|
||||
{
|
||||
CanBeFocused = segment.SegmentType != TutorialSegmentType.Objective,
|
||||
ToolTip = objectiveTextTranslated,
|
||||
OnClicked = (GUIButton btn, object userdata) =>
|
||||
ToolTip = objectiveTextTranslated
|
||||
};
|
||||
SetButtonBehavior(segment);
|
||||
SetTransparent(segment.ObjectiveButton);
|
||||
|
||||
frameRt.MoveOverTime(new Point(0, frameRt.AbsoluteOffset.Y), ObjectiveComponentAnimationTime, onDoneMoving: () => objectiveGroup?.Recalculate());
|
||||
|
||||
static void SetTransparent(GUIComponent component) => component.Color = component.HoverColor = component.PressedColor = component.SelectedColor = Color.Transparent;
|
||||
|
||||
void SetButtonBehavior(Segment segment)
|
||||
{
|
||||
segment.ObjectiveButton.CanBeFocused = segment.SegmentType != TutorialSegmentType.Objective;
|
||||
segment.ObjectiveButton.OnClicked = (GUIButton btn, object userdata) =>
|
||||
{
|
||||
if (segment.SegmentType == TutorialSegmentType.InfoBox)
|
||||
{
|
||||
@@ -621,13 +658,8 @@ namespace Barotrauma.Tutorials
|
||||
segment.OnClickObjective?.Invoke();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
SetTransparent(segment.ObjectiveButton);
|
||||
|
||||
frameRt.MoveOverTime(new Point(0, frameRt.AbsoluteOffset.Y), ObjectiveComponentAnimationTime, onDoneMoving: () => objectiveGroup?.Recalculate());
|
||||
|
||||
static void SetTransparent(GUIComponent component) => component.Color = component.HoverColor = component.PressedColor = component.SelectedColor = Color.Transparent;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private void ReplaySegmentVideo(Segment segment)
|
||||
|
||||
@@ -4,6 +4,7 @@ using Barotrauma.Networking;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace Barotrauma.Items.Components
|
||||
{
|
||||
@@ -177,7 +178,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
public void Draw(SpriteBatch spriteBatch, bool editing, float itemDepth = -1)
|
||||
{
|
||||
Color color = item.SpriteColor;
|
||||
Color color = item.GetSpriteColor(withHighlight: true);
|
||||
if (brokenSprite == null)
|
||||
{
|
||||
//broken doors turn black if no broken sprite has been configured
|
||||
@@ -220,11 +221,15 @@ namespace Barotrauma.Items.Components
|
||||
color, 0.0f, doorSprite.Origin, item.Scale, item.SpriteEffects, doorSprite.Depth);
|
||||
}
|
||||
|
||||
if (brokenSprite != null && item.Health < item.MaxCondition)
|
||||
float maxCondition = item.Repairables.Any() ?
|
||||
item.Repairables.Min(r => r.RepairThreshold) / 100.0f * item.MaxCondition :
|
||||
item.MaxCondition;
|
||||
float healthRatio = item.Health / maxCondition;
|
||||
if (brokenSprite != null && healthRatio < 1.0f)
|
||||
{
|
||||
Vector2 scale = scaleBrokenSprite ? new Vector2(1.0f - item.Health / item.MaxCondition) : Vector2.One;
|
||||
Vector2 scale = scaleBrokenSprite ? new Vector2(1.0f - healthRatio) : Vector2.One;
|
||||
if (IsHorizontal) { scale.X = 1; } else { scale.Y = 1; }
|
||||
float alpha = fadeBrokenSprite ? 1.0f - item.Health / item.MaxCondition : 1.0f;
|
||||
float alpha = fadeBrokenSprite ? 1.0f - healthRatio : 1.0f;
|
||||
spriteBatch.Draw(brokenSprite.Texture, pos,
|
||||
getSourceRect(brokenSprite, openState, IsHorizontal),
|
||||
color * alpha, 0.0f, brokenSprite.Origin, scale * item.Scale, item.SpriteEffects,
|
||||
|
||||
@@ -580,7 +580,7 @@ namespace Barotrauma.Items.Components
|
||||
GameMain.Instance.ResolutionChanged += OnResolutionChangedPrivate;
|
||||
}
|
||||
|
||||
protected void TryCreateDragHandle()
|
||||
protected virtual void TryCreateDragHandle()
|
||||
{
|
||||
if (GuiFrame != null && GuiFrameSource.GetAttributeBool("draggable", true))
|
||||
{
|
||||
@@ -593,6 +593,7 @@ namespace Barotrauma.Items.Components
|
||||
int iconHeight = GUIStyle.ItemFrameMargin.Y / 4;
|
||||
var dragIcon = new GUIImage(new RectTransform(new Point(GuiFrame.Rect.Width, iconHeight), handle.RectTransform, Anchor.TopCenter) { AbsoluteOffset = new Point(0, iconHeight / 2) },
|
||||
style: "GUIDragIndicatorHorizontal");
|
||||
dragIcon.RectTransform.MinSize = new Point(0, iconHeight);
|
||||
|
||||
handle.ValidatePosition = (RectTransform rectT) =>
|
||||
{
|
||||
@@ -622,7 +623,7 @@ namespace Barotrauma.Items.Components
|
||||
};
|
||||
|
||||
int buttonHeight = (int)(GUIStyle.ItemFrameMargin.Y * 0.4f);
|
||||
new GUIButton(new RectTransform(new Point(buttonHeight), handle.RectTransform, Anchor.TopLeft) { AbsoluteOffset = new Point(buttonHeight / 4) },
|
||||
new GUIButton(new RectTransform(new Point(buttonHeight), handle.RectTransform, Anchor.TopLeft) { AbsoluteOffset = new Point(buttonHeight / 4), MinSize = new Point(buttonHeight) },
|
||||
style: "GUIButtonSettings")
|
||||
{
|
||||
OnClicked = (btn, userdata) =>
|
||||
|
||||
@@ -324,6 +324,8 @@ namespace Barotrauma.Items.Components
|
||||
int i = 0;
|
||||
foreach (Item containedItem in Inventory.AllItems)
|
||||
{
|
||||
if (containedItem?.Sprite == null) { continue; }
|
||||
|
||||
if (AutoInteractWithContained)
|
||||
{
|
||||
containedItem.IsHighlighted = item.IsHighlighted;
|
||||
@@ -344,7 +346,7 @@ namespace Barotrauma.Items.Components
|
||||
containedItem.Sprite.Draw(
|
||||
spriteBatch,
|
||||
new Vector2(currentItemPos.X, -currentItemPos.Y),
|
||||
isWiringMode ? containedItem.GetSpriteColor() * 0.15f : containedItem.GetSpriteColor(),
|
||||
isWiringMode ? containedItem.GetSpriteColor(withHighlight: true) * 0.15f : containedItem.GetSpriteColor(withHighlight: true),
|
||||
origin,
|
||||
-(containedItem.body == null ? 0.0f : containedItem.body.DrawRotation ),
|
||||
containedItem.Scale,
|
||||
|
||||
@@ -96,6 +96,7 @@ namespace Barotrauma.Items.Components
|
||||
var buttonContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.4f, 0.8f), inputArea.RectTransform), childAnchor: Anchor.CenterLeft);
|
||||
activateButton = new GUIButton(new RectTransform(new Vector2(0.95f, 0.8f), buttonContainer.RectTransform), TextManager.Get("DeconstructorDeconstruct"), style: "DeviceButton")
|
||||
{
|
||||
UserData = UIHighlightAction.ElementId.DeconstructButton,
|
||||
TextBlock = { AutoScaleHorizontal = true },
|
||||
OnClicked = OnActivateButtonClicked
|
||||
};
|
||||
@@ -432,17 +433,22 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
private bool OnActivateButtonClicked(GUIButton button, object obj)
|
||||
{
|
||||
var disallowedItem = inputContainer.Inventory.FindItem(i => !i.AllowDeconstruct, recursive: false);
|
||||
if (disallowedItem != null && !DeconstructItemsSimultaneously)
|
||||
if (!IsActive)
|
||||
{
|
||||
int index = inputContainer.Inventory.FindIndex(disallowedItem);
|
||||
if (index >= 0 && index < inputContainer.Inventory.visualSlots.Length)
|
||||
//don't allow turning on if there's non-deconstructable items in the queue
|
||||
var disallowedItem = inputContainer.Inventory.FindItem(i => !i.AllowDeconstruct, recursive: false);
|
||||
if (disallowedItem != null && !DeconstructItemsSimultaneously)
|
||||
{
|
||||
var slot = inputContainer.Inventory.visualSlots[index];
|
||||
slot?.ShowBorderHighlight(GUIStyle.Red, 0.1f, 0.9f);
|
||||
int index = inputContainer.Inventory.FindIndex(disallowedItem);
|
||||
if (index >= 0 && index < inputContainer.Inventory.visualSlots.Length)
|
||||
{
|
||||
var slot = inputContainer.Inventory.visualSlots[index];
|
||||
slot?.ShowBorderHighlight(GUIStyle.Red, 0.1f, 0.9f);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (GameMain.Client != null)
|
||||
{
|
||||
pendingState = !IsActive;
|
||||
|
||||
@@ -32,6 +32,8 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
private FabricationRecipe selectedItem;
|
||||
|
||||
public Identifier SelectedItemIdentifier => SelectedItem?.TargetItem.Identifier ?? Identifier.Empty;
|
||||
|
||||
private GUIComponent inSufficientPowerWarning;
|
||||
|
||||
private FabricationRecipe pendingFabricatedItem;
|
||||
|
||||
@@ -1013,12 +1013,14 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
else if (hullData.LinkedHulls.Any())
|
||||
{
|
||||
hullData.HullWaterAmount = 0.0f;
|
||||
float waterVolume = 0.0f;
|
||||
float totalVolume = 0.0f;
|
||||
foreach (Hull linkedHull in hullData.LinkedHulls)
|
||||
{
|
||||
hullData.HullWaterAmount += WaterDetector.GetWaterPercentage(linkedHull);
|
||||
waterVolume += linkedHull.WaterVolume;
|
||||
totalVolume += linkedHull.Volume;
|
||||
}
|
||||
hullData.HullWaterAmount /= hullData.LinkedHulls.Count;
|
||||
hullData.HullWaterAmount = MathHelper.Clamp((int)Math.Ceiling(waterVolume / totalVolume * 100), 0, 100);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
using Barotrauma.Networking;
|
||||
using Barotrauma.Particles;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma.Items.Components
|
||||
{
|
||||
@@ -58,6 +56,7 @@ namespace Barotrauma.Items.Components
|
||||
RelativeOffset = new Vector2(0, 0.1f)
|
||||
}, style: "PowerButton")
|
||||
{
|
||||
UserData = UIHighlightAction.ElementId.PowerButton,
|
||||
OnClicked = (button, data) =>
|
||||
{
|
||||
TargetLevel = null;
|
||||
@@ -114,6 +113,7 @@ namespace Barotrauma.Items.Components
|
||||
return true;
|
||||
}
|
||||
};
|
||||
pumpSpeedSlider.Frame.UserData = UIHighlightAction.ElementId.PumpSpeedSlider;
|
||||
var textsArea = new GUIFrame(new RectTransform(new Vector2(1, 0.25f), sliderArea.RectTransform, Anchor.BottomCenter), style: null);
|
||||
var outLabel = new GUITextBlock(new RectTransform(new Vector2(0.5f, 1.0f), textsArea.RectTransform, Anchor.CenterLeft), TextManager.Get("PumpOut"),
|
||||
textColor: GUIStyle.TextColorNormal, textAlignment: Alignment.CenterLeft, wrap: false, font: GUIStyle.SubHeadingFont);
|
||||
|
||||
@@ -234,6 +234,7 @@ namespace Barotrauma.Items.Components
|
||||
return false;
|
||||
}
|
||||
};
|
||||
FissionRateScrollBar.Frame.UserData = UIHighlightAction.ElementId.FissionRateSlider;
|
||||
|
||||
TurbineOutputScrollBar = new GUIScrollBar(new RectTransform(sliderSize, rightArea.RectTransform, Anchor.TopCenter)
|
||||
{
|
||||
@@ -252,6 +253,7 @@ namespace Barotrauma.Items.Components
|
||||
return false;
|
||||
}
|
||||
};
|
||||
TurbineOutputScrollBar.Frame.UserData = UIHighlightAction.ElementId.TurbineOutputSlider;
|
||||
|
||||
var buttonArea = new GUILayoutGroup(new RectTransform(new Vector2(1, 0.2f), columnLeft.RectTransform))
|
||||
{
|
||||
@@ -305,6 +307,7 @@ namespace Barotrauma.Items.Components
|
||||
AutoTempSwitch = new GUIButton(new RectTransform(new Vector2(0.15f, 0.9f), topRightArea.RectTransform),
|
||||
style: "SwitchVertical")
|
||||
{
|
||||
UserData = UIHighlightAction.ElementId.AutoTempSwitch,
|
||||
Enabled = false,
|
||||
Selected = AutoTemp,
|
||||
ClickSound = GUISoundType.UISwitch,
|
||||
@@ -347,6 +350,7 @@ namespace Barotrauma.Items.Components
|
||||
RelativeOffset = new Vector2(0, 0.1f)
|
||||
}, style: "PowerButton")
|
||||
{
|
||||
UserData = UIHighlightAction.ElementId.PowerButton,
|
||||
OnClicked = (button, data) =>
|
||||
{
|
||||
PowerOn = !PowerOn;
|
||||
|
||||
@@ -216,6 +216,7 @@ namespace Barotrauma.Items.Components
|
||||
var sonarModeArea = new GUIFrame(new RectTransform(new Vector2(1, 0.4f + extraHeight), paddedControlContainer.RectTransform, Anchor.TopCenter), style: null);
|
||||
SonarModeSwitch = new GUIButton(new RectTransform(new Vector2(0.2f, 1), sonarModeArea.RectTransform), string.Empty, style: "SwitchVertical")
|
||||
{
|
||||
UserData = UIHighlightAction.ElementId.SonarModeSwitch,
|
||||
Selected = false,
|
||||
Enabled = true,
|
||||
ClickSound = GUISoundType.UISwitch,
|
||||
@@ -238,6 +239,7 @@ namespace Barotrauma.Items.Components
|
||||
passiveTickBox = new GUITickBox(new RectTransform(new Vector2(1, 0.45f), sonarModeRightSide.RectTransform, Anchor.TopLeft),
|
||||
TextManager.Get("SonarPassive"), font: GUIStyle.SubHeadingFont, style: "IndicatorLightRedSmall")
|
||||
{
|
||||
UserData = UIHighlightAction.ElementId.PassiveSonarIndicator,
|
||||
ToolTip = TextManager.Get("SonarTipPassive"),
|
||||
Selected = true,
|
||||
Enabled = false
|
||||
@@ -245,6 +247,7 @@ namespace Barotrauma.Items.Components
|
||||
activeTickBox = new GUITickBox(new RectTransform(new Vector2(1, 0.45f), sonarModeRightSide.RectTransform, Anchor.BottomLeft),
|
||||
TextManager.Get("SonarActive"), font: GUIStyle.SubHeadingFont, style: "IndicatorLightRedSmall")
|
||||
{
|
||||
UserData = UIHighlightAction.ElementId.ActiveSonarIndicator,
|
||||
ToolTip = TextManager.Get("SonarTipActive"),
|
||||
Selected = false,
|
||||
Enabled = false
|
||||
@@ -279,9 +282,14 @@ namespace Barotrauma.Items.Components
|
||||
};
|
||||
|
||||
new GUIFrame(new RectTransform(new Vector2(0.8f, 0.01f), paddedControlContainer.RectTransform, Anchor.Center), style: "HorizontalLine")
|
||||
{ UserData = "horizontalline" };
|
||||
{
|
||||
UserData = "horizontalline"
|
||||
};
|
||||
|
||||
var directionalModeFrame = new GUIFrame(new RectTransform(new Vector2(1, 0.45f), lowerAreaFrame.RectTransform, Anchor.BottomCenter), style: null);
|
||||
var directionalModeFrame = new GUIFrame(new RectTransform(new Vector2(1, 0.45f), lowerAreaFrame.RectTransform, Anchor.BottomCenter), style: null)
|
||||
{
|
||||
UserData = UIHighlightAction.ElementId.DirectionalSonarFrame
|
||||
};
|
||||
directionalModeSwitch = new GUIButton(new RectTransform(new Vector2(0.3f, 0.8f), directionalModeFrame.RectTransform, Anchor.CenterLeft), string.Empty, style: "SwitchHorizontal")
|
||||
{
|
||||
OnClicked = (button, data) =>
|
||||
@@ -334,6 +342,18 @@ namespace Barotrauma.Items.Components
|
||||
sonarView.RectTransform.RelativeOffset = new Vector2(0.13f * GUI.RelativeHorizontalAspectRatio, 0);
|
||||
sonarView.RectTransform.SetPosition(Anchor.BottomRight);
|
||||
}
|
||||
var handle = GuiFrame.GetChild<GUIDragHandle>();
|
||||
if (handle != null)
|
||||
{
|
||||
handle.RectTransform.Parent = controlContainer.RectTransform;
|
||||
handle.RectTransform.Resize(Vector2.One);
|
||||
handle.RectTransform.SetAsFirstChild();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void TryCreateDragHandle()
|
||||
{
|
||||
base.TryCreateDragHandle();
|
||||
}
|
||||
|
||||
private void SetPingDirection(Vector2 direction)
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
using Barotrauma.Networking;
|
||||
using Barotrauma.Extensions;
|
||||
using Barotrauma.Networking;
|
||||
using FarseerPhysics;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Input;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using System.Xml.Linq;
|
||||
using Barotrauma.Extensions;
|
||||
using System.Linq;
|
||||
|
||||
namespace Barotrauma.Items.Components
|
||||
{
|
||||
@@ -141,6 +139,7 @@ namespace Barotrauma.Items.Components
|
||||
var steeringModeArea = new GUIFrame(new RectTransform(new Vector2(1, 0.4f), paddedControlContainer.RectTransform, Anchor.TopLeft), style: null);
|
||||
steeringModeSwitch = new GUIButton(new RectTransform(new Vector2(0.2f, 1), steeringModeArea.RectTransform), string.Empty, style: "SwitchVertical")
|
||||
{
|
||||
UserData = UIHighlightAction.ElementId.SteeringModeSwitch,
|
||||
Selected = autoPilot,
|
||||
Enabled = true,
|
||||
ClickSound = GUISoundType.UISwitch,
|
||||
@@ -182,6 +181,7 @@ namespace Barotrauma.Items.Components
|
||||
maintainPosTickBox = new GUITickBox(new RectTransform(new Vector2(1, 0.333f), paddedAutoPilotControls.RectTransform, Anchor.TopCenter),
|
||||
TextManager.Get("SteeringMaintainPos"), font: GUIStyle.SmallFont, style: "GUIRadioButton")
|
||||
{
|
||||
UserData = UIHighlightAction.ElementId.MaintainPosTickBox,
|
||||
Enabled = autoPilot,
|
||||
Selected = maintainPos,
|
||||
OnSelected = tickBox =>
|
||||
|
||||
@@ -83,6 +83,7 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
};
|
||||
rechargeSpeedSlider.Bar.RectTransform.MaxSize = new Point(rechargeSpeedSlider.Bar.Rect.Height);
|
||||
rechargeSpeedSlider.Frame.UserData = UIHighlightAction.ElementId.RechargeSpeedSlider;
|
||||
|
||||
// lower area --------------------------
|
||||
|
||||
|
||||
@@ -165,6 +165,7 @@ namespace Barotrauma.Items.Components
|
||||
repairingText = TextManager.Get("Repairing");
|
||||
RepairButton = new GUIButton(new RectTransform(new Vector2(0.4f, 1.0f), progressBarHolder.RectTransform, Anchor.TopCenter), repairButtonText)
|
||||
{
|
||||
UserData = UIHighlightAction.ElementId.RepairButton,
|
||||
OnClicked = (btn, obj) =>
|
||||
{
|
||||
requestStartFixAction = FixActions.Repair;
|
||||
|
||||
@@ -135,7 +135,7 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
else
|
||||
{
|
||||
DebugConsole.ShowError($"Error creating a CustomInterface component: unexpected NumberType \"{(ciElement.NumberType.HasValue ? ciElement.NumberType.Value.ToString() : "none")}\"");
|
||||
DebugConsole.LogError($"Error creating a CustomInterface component: unexpected NumberType \"{(ciElement.NumberType.HasValue ? ciElement.NumberType.Value.ToString() : "none")}\"");
|
||||
}
|
||||
if (numberInput != null)
|
||||
{
|
||||
|
||||
@@ -118,7 +118,7 @@ namespace Barotrauma
|
||||
return GetDrawDepth(SpriteDepth + DrawDepthOffset, Sprite);
|
||||
}
|
||||
|
||||
public Color GetSpriteColor()
|
||||
public Color GetSpriteColor(bool withHighlight = false)
|
||||
{
|
||||
Color color = spriteColor;
|
||||
if (Prefab.UseContainedSpriteColor && ownInventory != null)
|
||||
@@ -129,6 +129,17 @@ namespace Barotrauma
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (withHighlight)
|
||||
{
|
||||
if (IsHighlighted && !GUI.DisableItemHighlights && Screen.Selected != GameMain.GameScreen)
|
||||
{
|
||||
color = GUIStyle.Orange * Math.Max(GetSpriteColor().A / (float)byte.MaxValue, 0.1f);
|
||||
}
|
||||
else if (IsHighlighted && HighlightColor.HasValue)
|
||||
{
|
||||
color = Color.Lerp(color, HighlightColor.Value, (MathF.Sin((float)Timing.TotalTime * 3.0f) + 1.0f) / 2.0f);
|
||||
}
|
||||
}
|
||||
return color;
|
||||
}
|
||||
|
||||
@@ -281,9 +292,7 @@ namespace Barotrauma
|
||||
else if (!ShowItems) { return; }
|
||||
}
|
||||
|
||||
Color color = IsIncludedInSelection && editing ? GUIStyle.Blue : IsHighlighted && !GUI.DisableItemHighlights && Screen.Selected != GameMain.GameScreen ? GUIStyle.Orange * Math.Max(GetSpriteColor().A / (float) byte.MaxValue, 0.1f) : GetSpriteColor();
|
||||
|
||||
//if (IsSelected && editing) color = Color.Lerp(color, Color.Gold, 0.5f);
|
||||
Color color = IsIncludedInSelection && editing ? GUIStyle.Blue : GetSpriteColor(withHighlight: true);
|
||||
|
||||
bool isWiringMode = editing && SubEditorScreen.TransparentWiringMode && SubEditorScreen.IsWiringMode() && !isWire && parentInventory == null;
|
||||
bool renderTransparent = isWiringMode && GetComponent<ConnectionPanel>() == null;
|
||||
|
||||
@@ -229,6 +229,7 @@ namespace Barotrauma
|
||||
Submarine = Submarine.MainSub
|
||||
};
|
||||
item.SetTransform(ConvertUnits.ToSimUnits(Submarine.MainSub == null ? item.Position : item.Position - Submarine.MainSub.Position), 0.0f);
|
||||
item.GetComponent<Items.Components.Door>()?.RefreshLinkedGap();
|
||||
item.FindHull();
|
||||
item.Submarine = Submarine.MainSub;
|
||||
|
||||
|
||||
@@ -264,10 +264,6 @@ namespace Barotrauma
|
||||
{
|
||||
Vector2 velocity = flowForce;
|
||||
if (!IsHorizontal)
|
||||
{
|
||||
velocity.X = Rand.Range(-100.0f, 100.0f) * open;
|
||||
}
|
||||
else
|
||||
{
|
||||
velocity.X *= Rand.Range(1.0f, 3.0f);
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Barotrauma.Networking
|
||||
{
|
||||
@@ -88,12 +87,13 @@ namespace Barotrauma.Networking
|
||||
TextManager.Get("BanPermanent") : TextManager.GetWithVariable("BanExpires", "[time]", bannedPlayer.ExpirationTime.Value.ToString()),
|
||||
font: GUIStyle.SmallFont);
|
||||
|
||||
LocalizedString reason = TextManager.GetServerMessage(bannedPlayer.Reason).Fallback(bannedPlayer.Reason);
|
||||
var reasonText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), paddedPlayerFrame.RectTransform),
|
||||
TextManager.Get("BanReason") + " " +
|
||||
(string.IsNullOrEmpty(bannedPlayer.Reason) ? TextManager.Get("None") : bannedPlayer.Reason),
|
||||
(string.IsNullOrEmpty(bannedPlayer.Reason) ? TextManager.Get("None") : reason),
|
||||
font: GUIStyle.SmallFont, wrap: true)
|
||||
{
|
||||
ToolTip = bannedPlayer.Reason
|
||||
ToolTip = reason
|
||||
};
|
||||
|
||||
paddedPlayerFrame.Recalculate();
|
||||
|
||||
@@ -31,12 +31,17 @@ namespace Barotrauma.Networking
|
||||
|
||||
public bool IsOwner;
|
||||
|
||||
public bool AllowKicking;
|
||||
|
||||
public bool IsDownloading;
|
||||
|
||||
public float Karma;
|
||||
|
||||
public bool AllowKicking =>
|
||||
!IsOwner &&
|
||||
!HasPermission(ClientPermissions.Ban) &&
|
||||
!HasPermission(ClientPermissions.Kick) &&
|
||||
!HasPermission(ClientPermissions.Unban);
|
||||
|
||||
public void UpdateSoundPosition()
|
||||
{
|
||||
if (VoipSound == null) { return; }
|
||||
|
||||
@@ -362,8 +362,7 @@ namespace Barotrauma.Networking
|
||||
// When this is set to true, we are approved and ready to go
|
||||
canStart = false;
|
||||
|
||||
DateTime timeOut = DateTime.Now + new TimeSpan(0, 0, 40);
|
||||
DateTime reqAuthTime = DateTime.Now + new TimeSpan(0, 0, 0, 0, 200);
|
||||
DateTime timeOut = DateTime.Now + new TimeSpan(0, 0, 200);
|
||||
|
||||
// Loop until we are approved
|
||||
LocalizedString connectingText = TextManager.Get("Connecting");
|
||||
@@ -489,7 +488,10 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
GameAnalyticsManager.AddErrorEventOnce("GameClient.Update:CheckServerMessagesException" + e.TargetSite.ToString(), GameAnalyticsManager.ErrorSeverity.Error, errorMsg);
|
||||
DebugConsole.ThrowError("Error while reading a message from server.", e);
|
||||
new GUIMessageBox(TextManager.Get("Error"), TextManager.GetWithVariables("MessageReadError", ("[message]", e.Message), ("[targetsite]", e.TargetSite.ToString())));
|
||||
new GUIMessageBox(TextManager.Get("Error"), TextManager.GetWithVariables("MessageReadError", ("[message]", e.Message), ("[targetsite]", e.TargetSite.ToString())))
|
||||
{
|
||||
DisplayInLoadingScreens = true
|
||||
};
|
||||
Quit();
|
||||
GameMain.ServerListScreen.Select();
|
||||
return;
|
||||
@@ -965,10 +967,10 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
AttemptReconnect(disconnectPacket);
|
||||
}
|
||||
else if (disconnectPacket.ShouldShowMessage)
|
||||
else
|
||||
{
|
||||
ReturnToPreviousMenu(null, null);
|
||||
var msgBox = new GUIMessageBox(TextManager.Get(wasConnected ? "ConnectionLost" : "CouldNotConnectToServer"), disconnectPacket.PopupMessage)
|
||||
new GUIMessageBox(TextManager.Get(wasConnected ? "ConnectionLost" : "CouldNotConnectToServer"), disconnectPacket.PopupMessage)
|
||||
{
|
||||
DisplayInLoadingScreens = true
|
||||
};
|
||||
@@ -1033,6 +1035,7 @@ namespace Barotrauma.Networking
|
||||
if (ClientPeer != null)
|
||||
{
|
||||
//restore the previous list of content packages so we can reconnect immediately without having to recheck that the packages match
|
||||
ClientPeer.ContentPackageOrderReceived = true;
|
||||
ClientPeer.ServerContentPackages = prevContentPackages;
|
||||
}
|
||||
}
|
||||
@@ -1721,6 +1724,7 @@ namespace Barotrauma.Networking
|
||||
string subName = inc.ReadString();
|
||||
string subHash = inc.ReadString();
|
||||
byte subClass = inc.ReadByte();
|
||||
bool isShuttle = inc.ReadBoolean();
|
||||
bool requiredContentPackagesInstalled = inc.ReadBoolean();
|
||||
|
||||
var matchingSub = SubmarineInfo.SavedSubmarines.FirstOrDefault(s => s.Name == subName && s.MD5Hash.StringRepresentation == subHash);
|
||||
@@ -1730,6 +1734,7 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
SubmarineClass = (SubmarineClass)subClass
|
||||
};
|
||||
if (isShuttle) { matchingSub.AddTag(SubmarineTag.Shuttle); }
|
||||
}
|
||||
matchingSub.RequiredContentPackagesInstalled = requiredContentPackagesInstalled;
|
||||
ServerSubmarines.Add(matchingSub);
|
||||
@@ -1780,7 +1785,6 @@ namespace Barotrauma.Networking
|
||||
AccountInfo = tc.AccountInfo,
|
||||
Muted = tc.Muted,
|
||||
InGame = tc.InGame,
|
||||
AllowKicking = tc.AllowKicking,
|
||||
IsOwner = tc.IsOwner
|
||||
};
|
||||
otherClients.Add(existingClient);
|
||||
@@ -1795,7 +1799,6 @@ namespace Barotrauma.Networking
|
||||
existingClient.Muted = tc.Muted;
|
||||
existingClient.InGame = tc.InGame;
|
||||
existingClient.IsOwner = tc.IsOwner;
|
||||
existingClient.AllowKicking = tc.AllowKicking;
|
||||
existingClient.IsDownloading = tc.IsDownloading;
|
||||
GameMain.NetLobbyScreen.SetPlayerNameAndJobPreference(existingClient);
|
||||
if (Screen.Selected != GameMain.NetLobbyScreen && tc.CharacterId > 0)
|
||||
@@ -2404,7 +2407,7 @@ namespace Barotrauma.Networking
|
||||
var subElement = subListChildren.FirstOrDefault(c =>
|
||||
((SubmarineInfo)c.UserData).Name == newSub.Name &&
|
||||
((SubmarineInfo)c.UserData).MD5Hash.StringRepresentation == newSub.MD5Hash.StringRepresentation);
|
||||
if (subElement == null) continue;
|
||||
if (subElement == null) { continue; }
|
||||
|
||||
Color newSubTextColor = new Color(subElement.GetChild<GUITextBlock>().TextColor, 1.0f);
|
||||
subElement.GetChild<GUITextBlock>().TextColor = newSubTextColor;
|
||||
@@ -2429,7 +2432,7 @@ namespace Barotrauma.Networking
|
||||
|
||||
if (GameMain.NetLobbyScreen.FailedSelectedShuttle.HasValue &&
|
||||
GameMain.NetLobbyScreen.FailedSelectedShuttle.Value.Name == newSub.Name &&
|
||||
GameMain.NetLobbyScreen.FailedSelectedShuttle.Value.Name == newSub.MD5Hash.StringRepresentation)
|
||||
GameMain.NetLobbyScreen.FailedSelectedShuttle.Value.Hash == newSub.MD5Hash.StringRepresentation)
|
||||
{
|
||||
GameMain.NetLobbyScreen.TrySelectSub(newSub.Name, newSub.MD5Hash.StringRepresentation, GameMain.NetLobbyScreen.ShuttleList.ListBox);
|
||||
}
|
||||
@@ -2583,6 +2586,7 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
}
|
||||
ChildServerRelay.ShutDown();
|
||||
GUIMessageBox.MessageBoxes.RemoveAll(c => c?.UserData is RoundSummary);
|
||||
|
||||
characterInfo?.Remove();
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ namespace Barotrauma.Networking
|
||||
protected abstract void SendMsgInternal(PeerPacketHeaders headers, INetSerializableStruct? body);
|
||||
|
||||
protected ConnectionInitialization initializationStep;
|
||||
public bool ContentPackageOrderReceived { get; protected set; }
|
||||
public bool ContentPackageOrderReceived { get; set; }
|
||||
protected int passwordSalt;
|
||||
protected Steamworks.AuthTicket? steamAuthTicket;
|
||||
private GUIMessageBox? passwordMsgBox;
|
||||
|
||||
@@ -36,6 +36,8 @@ namespace Barotrauma.Networking
|
||||
|
||||
public override void Start()
|
||||
{
|
||||
if (isActive) { return; }
|
||||
|
||||
ContentPackageOrderReceived = false;
|
||||
|
||||
steamAuthTicket = SteamManager.GetAuthSessionTicket();
|
||||
@@ -189,6 +191,7 @@ namespace Barotrauma.Networking
|
||||
if (packet is { SteamId: var steamId, Data: var data })
|
||||
{
|
||||
OnP2PData(steamId, data, data.Length);
|
||||
if (!isActive) { return; }
|
||||
receivedBytes += data.Length;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -391,7 +391,7 @@ namespace Barotrauma.Networking
|
||||
|
||||
for (int i = remotePeers.Count - 1; i >= 0; i--)
|
||||
{
|
||||
DisconnectPeer(remotePeers[i], peerDisconnectPacket);
|
||||
DisconnectPeer(remotePeers[i], PeerDisconnectPacket.WithReason(DisconnectReason.ServerShutdown));
|
||||
}
|
||||
|
||||
Thread.Sleep(100);
|
||||
|
||||
@@ -37,6 +37,7 @@ namespace Barotrauma.Networking
|
||||
switch (serverInfo.Endpoint)
|
||||
{
|
||||
case LidgrenEndpoint { NetEndpoint: { Address: var address } }:
|
||||
|
||||
GetIPAddressPing(serverInfo, address, onPingDiscovered);
|
||||
break;
|
||||
case SteamP2PEndpoint steamP2PEndpoint:
|
||||
@@ -132,24 +133,30 @@ namespace Barotrauma.Networking
|
||||
|
||||
private static void GetIPAddressPing(ServerInfo serverInfo, IPAddress address, Action<ServerInfo> onPingDiscovered)
|
||||
{
|
||||
lock (activePings)
|
||||
if (IPAddress.IsLoopback(address))
|
||||
{
|
||||
if (activePings.ContainsKey(address)) { return; }
|
||||
activePings.Add(address, activePings.Any() ? activePings.Values.Max() + 1 : 0);
|
||||
serverInfo.Ping = Option<int>.Some(0);
|
||||
onPingDiscovered(serverInfo);
|
||||
}
|
||||
|
||||
serverInfo.Ping = Option<int>.None();
|
||||
|
||||
TaskPool.Add($"PingServerAsync ({address})", PingServerAsync(address, 1000),
|
||||
rtt =>
|
||||
else
|
||||
{
|
||||
lock (activePings)
|
||||
{
|
||||
if (!rtt.TryGetResult(out serverInfo.Ping)) { serverInfo.Ping = Option<int>.None(); }
|
||||
onPingDiscovered(serverInfo);
|
||||
lock (activePings)
|
||||
if (activePings.ContainsKey(address)) { return; }
|
||||
activePings.Add(address, activePings.Any() ? activePings.Values.Max() + 1 : 0);
|
||||
}
|
||||
serverInfo.Ping = Option<int>.None();
|
||||
TaskPool.Add($"PingServerAsync ({address})", PingServerAsync(address, 1000),
|
||||
rtt =>
|
||||
{
|
||||
activePings.Remove(address);
|
||||
}
|
||||
});
|
||||
if (!rtt.TryGetResult(out serverInfo.Ping)) { serverInfo.Ping = Option<int>.None(); }
|
||||
onPingDiscovered(serverInfo);
|
||||
lock (activePings)
|
||||
{
|
||||
activePings.Remove(address);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private static async Task<Option<int>> PingServerAsync(IPAddress ipAddress, int timeOut)
|
||||
|
||||
@@ -70,7 +70,7 @@ namespace Barotrauma.Networking
|
||||
[Serialize(PlayStyle.Casual, IsPropertySaveable.Yes)]
|
||||
public PlayStyle PlayStyle { get; set; }
|
||||
|
||||
public Version GameVersion { get; set; } = new Version(0,0,0,0);
|
||||
public Version GameVersion { get; set; } = new Version(0, 0, 0, 0);
|
||||
|
||||
public Option<int> Ping = Option<int>.None();
|
||||
|
||||
@@ -200,7 +200,7 @@ namespace Barotrauma.Networking
|
||||
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), frame.RectTransform),
|
||||
TextManager.AddPunctuation(':', TextManager.Get("ServerListVersion"),
|
||||
GameVersion.ToString()))
|
||||
GameVersion == new Version(0, 0, 0, 0) ? TextManager.Get("Unknown") : GameVersion.ToString()))
|
||||
{
|
||||
CanBeFocused = false
|
||||
};
|
||||
@@ -397,10 +397,10 @@ namespace Barotrauma.Networking
|
||||
public void UpdateInfo(Func<string, string?> valueGetter)
|
||||
{
|
||||
ServerMessage = valueGetter("message") ?? "";
|
||||
GameVersion = Version.TryParse(valueGetter("version"), out var version)
|
||||
? version
|
||||
: GameMain.Version;
|
||||
|
||||
if (Version.TryParse(valueGetter("version"), out var version))
|
||||
{
|
||||
GameVersion = version;
|
||||
}
|
||||
if (int.TryParse(valueGetter("playercount"), out int playerCount)) { PlayerCount = playerCount; }
|
||||
if (int.TryParse(valueGetter("maxplayernum"), out int maxPlayers)) { MaxPlayers = maxPlayers; }
|
||||
if (Enum.TryParse(valueGetter("modeselectionmode"), out SelectionMode modeSelectionMode)) { ModeSelectionMode = modeSelectionMode; }
|
||||
|
||||
@@ -346,7 +346,7 @@ namespace Barotrauma
|
||||
};
|
||||
|
||||
var missionName = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionTextContent.RectTransform), mission?.Name ?? TextManager.Get("NoMission"), font: GUIStyle.SubHeadingFont, wrap: true);
|
||||
// missionName.RectTransform.MinSize = new Point(0, (int)(missionName.Rect.Height * 1.5f));
|
||||
missionName.RectTransform.MinSize = new Point(0, GUI.IntScale(15));
|
||||
if (mission != null)
|
||||
{
|
||||
var tickBox = new GUITickBox(new RectTransform(Vector2.One * 0.9f, missionName.RectTransform, anchor: Anchor.CenterLeft, scaleBasis: ScaleBasis.Smallest) { AbsoluteOffset = new Point((int)missionName.Padding.X, 0) }, label: string.Empty)
|
||||
|
||||
@@ -67,7 +67,9 @@ namespace Barotrauma
|
||||
|
||||
public static readonly Queue<ulong> WorkshopItemsToUpdate = new Queue<ulong>();
|
||||
|
||||
private readonly GUIListBox tutorialList;
|
||||
private GUIImage tutorialBanner;
|
||||
private GUITextBlock tutorialHeader, tutorialDescription;
|
||||
private GUIListBox tutorialList;
|
||||
|
||||
#region Creation
|
||||
public MainMenuScreen(GameMain game)
|
||||
@@ -429,20 +431,7 @@ namespace Barotrauma
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
menuTabs[Tab.Tutorials] = new GUIFrame(new RectTransform(relativeSize, GUI.Canvas, anchor, pivot, minSize, maxSize) { RelativeOffset = relativeSpacing });
|
||||
|
||||
//PLACEHOLDER
|
||||
tutorialList = new GUIListBox(
|
||||
new RectTransform(new Vector2(0.95f, 0.85f), menuTabs[Tab.Tutorials].RectTransform, Anchor.TopCenter) { RelativeOffset = new Vector2(0.0f, 0.1f) })
|
||||
{
|
||||
PlaySoundOnSelect = true,
|
||||
};
|
||||
tutorialList.OnSelected += (component, obj) =>
|
||||
{
|
||||
(obj as Tutorial)?.Start();
|
||||
return true;
|
||||
};
|
||||
|
||||
CreateTutorialButtons();
|
||||
CreateTutorialTab();
|
||||
|
||||
this.game = game;
|
||||
|
||||
@@ -459,24 +448,68 @@ namespace Barotrauma
|
||||
creditsPlayer = new CreditsPlayer(new RectTransform(Vector2.One, creditsContainer.RectTransform), "Content/Texts/Credits.xml");
|
||||
}
|
||||
|
||||
private void CreateTutorialButtons()
|
||||
private void CreateTutorialTab()
|
||||
{
|
||||
var tutorialInnerFrame = new GUIFrame(new RectTransform(new Vector2(0.9f, 0.9f), menuTabs[Tab.Tutorials].RectTransform, Anchor.Center), style: "InnerFrame");
|
||||
var tutorialContent = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.95f), tutorialInnerFrame.RectTransform, Anchor.Center), isHorizontal: true) { RelativeSpacing = 0.02f, Stretch = true };
|
||||
|
||||
tutorialList = new GUIListBox(new RectTransform(new Vector2(0.4f, 1.0f), tutorialContent.RectTransform))
|
||||
{
|
||||
PlaySoundOnSelect = true,
|
||||
OnSelected = (component, obj) =>
|
||||
{
|
||||
SelectTutorial(obj as Tutorial);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
var tutorialPreview = new GUILayoutGroup(new RectTransform(new Vector2(0.6f, 1.0f), tutorialContent.RectTransform)) { RelativeSpacing = 0.05f, Stretch = true };
|
||||
var imageContainer = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.6f), tutorialPreview.RectTransform), style: "InnerFrame");
|
||||
tutorialBanner = new GUIImage(new RectTransform(Vector2.One, imageContainer.RectTransform), style: null, scaleToFit: true);
|
||||
|
||||
var infoContainer = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.4f), tutorialPreview.RectTransform), style: "GUIFrameListBox");
|
||||
var infoContent = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.9f), infoContainer.RectTransform, Anchor.Center), childAnchor: Anchor.TopCenter);
|
||||
|
||||
tutorialHeader = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.75f), infoContent.RectTransform), string.Empty, font: GUIStyle.SubHeadingFont, textAlignment: Alignment.Center);
|
||||
|
||||
var startButton = new GUIButton(new RectTransform(new Vector2(0.5f, 0.0f), infoContent.RectTransform, Anchor.BottomRight), text: TextManager.Get("startgamebutton"))
|
||||
{
|
||||
IgnoreLayoutGroups = true,
|
||||
OnClicked = (component, obj) =>
|
||||
{
|
||||
(tutorialList.SelectedData as Tutorial)?.Start();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
Tutorial firstTutorial = null;
|
||||
foreach (var tutorialPrefab in TutorialPrefab.Prefabs.OrderBy(p => p.Order))
|
||||
{
|
||||
var tutorial = new Tutorial(tutorialPrefab);
|
||||
var tutorialText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.15f), tutorialList.Content.RectTransform), tutorial.DisplayName, textAlignment: Alignment.Center, font: GUIStyle.LargeFont)
|
||||
firstTutorial ??= tutorial;
|
||||
var tutorialText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), tutorialList.Content.RectTransform), tutorial.DisplayName)
|
||||
{
|
||||
TextColor = GUIStyle.Green,
|
||||
Padding = new Vector4(30.0f * GUI.Scale, 0,0,0),
|
||||
UserData = tutorial
|
||||
};
|
||||
tutorialText.RectTransform.MinSize = new Point(0, (int)(tutorialText.TextSize.Y * 2));
|
||||
}
|
||||
GUITextBlock.AutoScaleAndNormalize(tutorialList.Content.Children.Select(c => c as GUITextBlock));
|
||||
tutorialList.Select(firstTutorial);
|
||||
}
|
||||
|
||||
private void SelectTutorial(Tutorial tutorial)
|
||||
{
|
||||
tutorialHeader.Text = tutorial.DisplayName;
|
||||
tutorial.TutorialPrefab.Banner?.EnsureLazyLoaded();
|
||||
tutorialBanner.Sprite = tutorial.TutorialPrefab.Banner;
|
||||
tutorialBanner.Color = tutorial.TutorialPrefab.Banner == null ? Color.Black : Color.White;
|
||||
}
|
||||
|
||||
public static void UpdateInstanceTutorialButtons()
|
||||
{
|
||||
if (GameMain.MainMenuScreen is not MainMenuScreen menuScreen) { return; }
|
||||
menuScreen.tutorialList.ClearChildren();
|
||||
menuScreen.CreateTutorialButtons();
|
||||
menuScreen.CreateTutorialTab();
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -746,12 +779,13 @@ namespace Barotrauma
|
||||
|
||||
private void UpdateTutorialList()
|
||||
{
|
||||
foreach (GUITextBlock tutorialText in menuTabs[Tab.Tutorials].GetChild<GUIListBox>().Content.Children)
|
||||
foreach (GUITextBlock tutorialText in tutorialList.Content.Children)
|
||||
{
|
||||
var tutorial = (Tutorial)tutorialText.UserData;
|
||||
tutorialText.Text = CompletedTutorials.Instance.Contains(tutorial.Identifier) ?
|
||||
TextManager.GetWithVariable("tutorialcompleted", "[tutorialname]", tutorial.DisplayName) :
|
||||
tutorial.DisplayName;
|
||||
if (CompletedTutorials.Instance.Contains(tutorial.Identifier) && tutorialText.GetChild<GUIImage>() == null)
|
||||
{
|
||||
new GUIImage(new RectTransform(new Point((int)(tutorialText.Padding.X * 0.8f)), tutorialText.RectTransform, Anchor.CenterLeft), style: "ObjectiveIndicatorCompleted");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1862,7 +1862,7 @@ namespace Barotrauma
|
||||
SubmarineType.Wreck => "Content/Map/Wrecks/{0}",
|
||||
SubmarineType.BeaconStation => "Content/Map/BeaconStations/{0}",
|
||||
SubmarineType.EnemySubmarine => "Content/Map/EnemySubmarines/{0}",
|
||||
SubmarineType.OutpostModule => "Content/Map/Outposts/{0}",
|
||||
SubmarineType.OutpostModule => MainSub.Info.FilePath.Contains("RuinModules") ? "Content/Map/RuinModules/{0}" : "Content/Map/Outposts/{0}",
|
||||
_ => throw new InvalidOperationException()
|
||||
}, savePath);
|
||||
modProject.ModVersion = "";
|
||||
|
||||
@@ -195,13 +195,13 @@ namespace Barotrauma.Sounds
|
||||
GainMultipliers[index] = gain;
|
||||
}
|
||||
}
|
||||
private Dictionary<string, CategoryModifier> categoryModifiers;
|
||||
|
||||
private readonly Dictionary<string, CategoryModifier> categoryModifiers = new Dictionary<string, CategoryModifier>();
|
||||
|
||||
public SoundManager()
|
||||
{
|
||||
loadedSounds = new List<Sound>();
|
||||
streamingThread = null;
|
||||
categoryModifiers = null;
|
||||
|
||||
sourcePools = new SoundSourcePool[2];
|
||||
playingChannels[(int)SourcePoolIndex.Default] = new SoundChannel[SOURCE_COUNT];
|
||||
@@ -235,7 +235,7 @@ namespace Barotrauma.Sounds
|
||||
CompressionDynamicRangeGain = 1.0f;
|
||||
}
|
||||
|
||||
private void SetAudioOutputDevice(string deviceName)
|
||||
private static void SetAudioOutputDevice(string deviceName)
|
||||
{
|
||||
var config = GameSettings.CurrentConfig;
|
||||
config.Audio.AudioOutputDevice = deviceName;
|
||||
@@ -249,7 +249,7 @@ namespace Barotrauma.Sounds
|
||||
DebugConsole.NewMessage($"Attempting to open ALC device \"{deviceName}\"");
|
||||
|
||||
alcDevice = IntPtr.Zero;
|
||||
int alcError = Al.NoError;
|
||||
int alcError;
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
alcDevice = Alc.OpenDevice(deviceName);
|
||||
@@ -371,8 +371,10 @@ namespace Barotrauma.Sounds
|
||||
throw new System.IO.FileNotFoundException($"Sound file \"{filePath}\" doesn't exist! Content package \"{(element.ContentPackage?.Name ?? "Unknown")}\".");
|
||||
}
|
||||
|
||||
var newSound = new OggSound(this, filePath, stream, xElement: element);
|
||||
newSound.BaseGain = element.GetAttributeFloat("volume", 1.0f);
|
||||
var newSound = new OggSound(this, filePath, stream, xElement: element)
|
||||
{
|
||||
BaseGain = element.GetAttributeFloat("volume", 1.0f)
|
||||
};
|
||||
float range = element.GetAttributeFloat("range", 1000.0f);
|
||||
newSound.BaseNear = range * 0.4f;
|
||||
newSound.BaseFar = range;
|
||||
@@ -537,14 +539,16 @@ namespace Barotrauma.Sounds
|
||||
{
|
||||
if (Disabled) { return; }
|
||||
category = category.ToLower();
|
||||
if (categoryModifiers == null) categoryModifiers = new Dictionary<string, CategoryModifier>();
|
||||
if (!categoryModifiers.ContainsKey(category))
|
||||
lock (categoryModifiers)
|
||||
{
|
||||
categoryModifiers.Add(category, new CategoryModifier(index, gain, false));
|
||||
}
|
||||
else
|
||||
{
|
||||
categoryModifiers[category].SetGainMultiplier(index, gain);
|
||||
if (!categoryModifiers.ContainsKey(category))
|
||||
{
|
||||
categoryModifiers.Add(category, new CategoryModifier(index, gain, false));
|
||||
}
|
||||
else
|
||||
{
|
||||
categoryModifiers[category].SetGainMultiplier(index, gain);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < playingChannels.Length; i++)
|
||||
@@ -562,23 +566,26 @@ namespace Barotrauma.Sounds
|
||||
}
|
||||
}
|
||||
|
||||
public float GetCategoryGainMultiplier(string category, int index=-1)
|
||||
public float GetCategoryGainMultiplier(string category, int index = -1)
|
||||
{
|
||||
if (Disabled) { return 0.0f; }
|
||||
category = category.ToLower();
|
||||
if (categoryModifiers == null || !categoryModifiers.ContainsKey(category)) return 1.0f;
|
||||
if (index < 0)
|
||||
lock (categoryModifiers)
|
||||
{
|
||||
float accumulatedMultipliers = 1.0f;
|
||||
for (int i = 0; i < categoryModifiers[category].GainMultipliers.Length; i++)
|
||||
if (categoryModifiers == null || !categoryModifiers.TryGetValue(category, out CategoryModifier categoryModifier)) { return 1.0f; }
|
||||
if (index < 0)
|
||||
{
|
||||
accumulatedMultipliers *= categoryModifiers[category].GainMultipliers[i];
|
||||
float accumulatedMultipliers = 1.0f;
|
||||
for (int i = 0; i < categoryModifier.GainMultipliers.Length; i++)
|
||||
{
|
||||
accumulatedMultipliers *= categoryModifier.GainMultipliers[i];
|
||||
}
|
||||
return accumulatedMultipliers;
|
||||
}
|
||||
else
|
||||
{
|
||||
return categoryModifier.GainMultipliers[index];
|
||||
}
|
||||
return accumulatedMultipliers;
|
||||
}
|
||||
else
|
||||
{
|
||||
return categoryModifiers[category].GainMultipliers[index];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -587,15 +594,16 @@ namespace Barotrauma.Sounds
|
||||
if (Disabled) { return; }
|
||||
|
||||
category = category.ToLower();
|
||||
|
||||
if (categoryModifiers == null) { categoryModifiers = new Dictionary<string, CategoryModifier>(); }
|
||||
if (!categoryModifiers.ContainsKey(category))
|
||||
lock (categoryModifiers)
|
||||
{
|
||||
categoryModifiers.Add(category, new CategoryModifier(0, 1.0f, muffle));
|
||||
}
|
||||
else
|
||||
{
|
||||
categoryModifiers[category].Muffle = muffle;
|
||||
if (!categoryModifiers.ContainsKey(category))
|
||||
{
|
||||
categoryModifiers.Add(category, new CategoryModifier(0, 1.0f, muffle));
|
||||
}
|
||||
else
|
||||
{
|
||||
categoryModifiers[category].Muffle = muffle;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < playingChannels.Length; i++)
|
||||
@@ -618,8 +626,11 @@ namespace Barotrauma.Sounds
|
||||
if (Disabled) { return false; }
|
||||
|
||||
category = category.ToLower();
|
||||
if (categoryModifiers == null || !categoryModifiers.ContainsKey(category)) { return false; }
|
||||
return categoryModifiers[category].Muffle;
|
||||
lock (categoryModifiers)
|
||||
{
|
||||
if (categoryModifiers == null || !categoryModifiers.TryGetValue(category, out CategoryModifier categoryModifier)) { return false; }
|
||||
return categoryModifier.Muffle;
|
||||
}
|
||||
}
|
||||
|
||||
public void Update()
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<RootNamespace>Barotrauma</RootNamespace>
|
||||
<Authors>FakeFish, Undertow Games</Authors>
|
||||
<Product>Barotrauma</Product>
|
||||
<Version>0.19.5.0</Version>
|
||||
<Version>0.19.8.0</Version>
|
||||
<Copyright>Copyright © FakeFish 2018-2022</Copyright>
|
||||
<Platforms>AnyCPU;x64</Platforms>
|
||||
<AssemblyName>Barotrauma</AssemblyName>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<RootNamespace>Barotrauma</RootNamespace>
|
||||
<Authors>FakeFish, Undertow Games</Authors>
|
||||
<Product>Barotrauma</Product>
|
||||
<Version>0.19.5.0</Version>
|
||||
<Version>0.19.8.0</Version>
|
||||
<Copyright>Copyright © FakeFish 2018-2022</Copyright>
|
||||
<Platforms>AnyCPU;x64</Platforms>
|
||||
<AssemblyName>Barotrauma</AssemblyName>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<RootNamespace>Barotrauma</RootNamespace>
|
||||
<Authors>FakeFish, Undertow Games</Authors>
|
||||
<Product>Barotrauma</Product>
|
||||
<Version>0.19.5.0</Version>
|
||||
<Version>0.19.8.0</Version>
|
||||
<Copyright>Copyright © FakeFish 2018-2022</Copyright>
|
||||
<Platforms>AnyCPU;x64</Platforms>
|
||||
<AssemblyName>Barotrauma</AssemblyName>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<RootNamespace>Barotrauma</RootNamespace>
|
||||
<Authors>FakeFish, Undertow Games</Authors>
|
||||
<Product>Barotrauma Dedicated Server</Product>
|
||||
<Version>0.19.5.0</Version>
|
||||
<Version>0.19.8.0</Version>
|
||||
<Copyright>Copyright © FakeFish 2018-2022</Copyright>
|
||||
<Platforms>AnyCPU;x64</Platforms>
|
||||
<AssemblyName>DedicatedServer</AssemblyName>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<RootNamespace>Barotrauma</RootNamespace>
|
||||
<Authors>FakeFish, Undertow Games</Authors>
|
||||
<Product>Barotrauma Dedicated Server</Product>
|
||||
<Version>0.19.5.0</Version>
|
||||
<Version>0.19.8.0</Version>
|
||||
<Copyright>Copyright © FakeFish 2018-2022</Copyright>
|
||||
<Platforms>AnyCPU;x64</Platforms>
|
||||
<AssemblyName>DedicatedServer</AssemblyName>
|
||||
|
||||
@@ -512,13 +512,10 @@ namespace Barotrauma
|
||||
msg.WriteByte((byte)TeamID);
|
||||
break;
|
||||
case AddToCrewEventData addToCrewEventData:
|
||||
msg.WriteByte((byte)addToCrewEventData.TeamType); // team id
|
||||
ushort[] inventoryItemIDs = addToCrewEventData.InventoryItems.Select(item => item.ID).ToArray();
|
||||
msg.WriteUInt16((ushort)inventoryItemIDs.Length);
|
||||
for (int i = 0; i < inventoryItemIDs.Length; i++)
|
||||
{
|
||||
msg.WriteUInt16(inventoryItemIDs[i]);
|
||||
}
|
||||
msg.WriteNetSerializableStruct(addToCrewEventData.ItemTeamChange);
|
||||
break;
|
||||
case RemoveFromCrewEventData removeFromCrewEventData:
|
||||
msg.WriteNetSerializableStruct(removeFromCrewEventData.ItemTeamChange);
|
||||
break;
|
||||
case UpdateExperienceEventData _:
|
||||
msg.WriteInt32(Info.ExperiencePoints);
|
||||
|
||||
@@ -1613,6 +1613,7 @@ namespace Barotrauma.Networking
|
||||
outmsg.WriteString(sub.Name);
|
||||
outmsg.WriteString(sub.MD5Hash.ToString());
|
||||
outmsg.WriteByte((byte)sub.SubmarineClass);
|
||||
outmsg.WriteBoolean(sub.HasTag(SubmarineTag.Shuttle));
|
||||
outmsg.WriteBoolean(sub.RequiredContentPackagesInstalled);
|
||||
}
|
||||
|
||||
@@ -1836,10 +1837,6 @@ namespace Barotrauma.Networking
|
||||
InGame = client.InGame,
|
||||
HasPermissions = client.Permissions != ClientPermissions.None,
|
||||
IsOwner = client.Connection == OwnerConnection,
|
||||
AllowKicking = client.Connection != OwnerConnection &&
|
||||
!client.HasPermission(ClientPermissions.Ban) &&
|
||||
!client.HasPermission(ClientPermissions.Kick) &&
|
||||
!client.HasPermission(ClientPermissions.Unban),
|
||||
IsDownloading = FileSender.ActiveTransfers.Any(t => t.Connection == client.Connection)
|
||||
};
|
||||
|
||||
@@ -3383,7 +3380,7 @@ namespace Barotrauma.Networking
|
||||
private IEnumerable<CoroutineStatus> SendClientPermissionsAfterClientListSynced(Client recipient, Client client)
|
||||
{
|
||||
DateTime timeOut = DateTime.Now + new TimeSpan(0, 0, 10);
|
||||
while (recipient.LastRecvClientListUpdate < LastClientListUpdateID)
|
||||
while (NetIdUtils.IdMoreRecent(LastClientListUpdateID, recipient.LastRecvClientListUpdate))
|
||||
{
|
||||
if (DateTime.Now > timeOut || GameMain.Server == null || !connectedClients.Contains(recipient))
|
||||
{
|
||||
|
||||
@@ -225,7 +225,7 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
else if (!packetHeader.IsConnectionInitializationStep())
|
||||
{
|
||||
if (!(connectedClients.Find(c => c is LidgrenConnection l && l.NetConnection == lidgrenMsg.SenderConnection) is LidgrenConnection conn))
|
||||
if (connectedClients.Find(c => c is LidgrenConnection l && l.NetConnection == lidgrenMsg.SenderConnection) is not LidgrenConnection conn)
|
||||
{
|
||||
if (pendingClient != null)
|
||||
{
|
||||
@@ -373,7 +373,7 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
if (netServer == null) { return; }
|
||||
|
||||
if (!(conn is LidgrenConnection lidgrenConn)) { return; }
|
||||
if (conn is not LidgrenConnection lidgrenConn) { return; }
|
||||
|
||||
if (connectedClients.Contains(lidgrenConn))
|
||||
{
|
||||
@@ -432,7 +432,7 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!packet.SteamId.TryUnwrap(out var id) || !(id is SteamId steamId))
|
||||
if (!packet.SteamId.TryUnwrap(out var id) || id is not SteamId steamId)
|
||||
{
|
||||
if (requireSteamAuth)
|
||||
{
|
||||
|
||||
@@ -167,7 +167,14 @@ namespace Barotrauma.Networking
|
||||
if (pendingClient.AccountInfo.AccountId.TryUnwrap(out var id)) { banAccountId(id); }
|
||||
|
||||
pendingClient.AccountInfo.OtherMatchingIds.ForEach(banAccountId);
|
||||
serverSettings.BanList.BanPlayer(pendingClient.Name ?? "Player", pendingClient.Connection.Endpoint, banReason, duration);
|
||||
if (pendingClient.AccountInfo.AccountId.TryUnwrap(out var accountId))
|
||||
{
|
||||
serverSettings.BanList.BanPlayer(pendingClient.Name ?? "Player", accountId, banReason, duration);
|
||||
}
|
||||
else
|
||||
{
|
||||
serverSettings.BanList.BanPlayer(pendingClient.Name ?? "Player", pendingClient.Connection.Endpoint, banReason, duration);
|
||||
}
|
||||
}
|
||||
|
||||
protected bool IsPendingClientBanned(PendingClient pendingClient, out string? banReason)
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
#nullable enable
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.Xna.Framework;
|
||||
|
||||
namespace Barotrauma.Networking
|
||||
{
|
||||
@@ -139,7 +137,27 @@ namespace Barotrauma.Networking
|
||||
pendingClient?.Heartbeat();
|
||||
connectedClient?.Heartbeat();
|
||||
|
||||
if (serverSettings.BanList.IsBanned(senderSteamId, out string banReason) ||
|
||||
if (packetHeader.IsConnectionInitializationStep())
|
||||
{
|
||||
if (!initialization.HasValue) { return; }
|
||||
ConnectionInitialization initializationStep = initialization.Value;
|
||||
|
||||
if (pendingClient != null)
|
||||
{
|
||||
pendingClient.Connection.SetAccountInfo(new AccountInfo(senderSteamId, sentOwnerSteamId));
|
||||
ReadConnectionInitializationStep(
|
||||
pendingClient,
|
||||
new ReadWriteMessage(inc.Buffer, inc.BitPosition, inc.LengthBits, false),
|
||||
initializationStep);
|
||||
}
|
||||
else if (initializationStep == ConnectionInitialization.ConnectionStarted)
|
||||
{
|
||||
pendingClient = new PendingClient(new SteamP2PConnection(senderSteamId));
|
||||
pendingClient.Connection.SetAccountInfo(new AccountInfo(senderSteamId, sentOwnerSteamId));
|
||||
pendingClients.Add(pendingClient);
|
||||
}
|
||||
}
|
||||
else if (serverSettings.BanList.IsBanned(senderSteamId, out string banReason) ||
|
||||
serverSettings.BanList.IsBanned(sentOwnerSteamId, out banReason))
|
||||
{
|
||||
if (pendingClient != null)
|
||||
@@ -167,24 +185,6 @@ namespace Barotrauma.Networking
|
||||
//message exists solely as a heartbeat, ignore its contents
|
||||
return;
|
||||
}
|
||||
else if (packetHeader.IsConnectionInitializationStep())
|
||||
{
|
||||
if (!initialization.HasValue) { return; }
|
||||
ConnectionInitialization initializationStep = initialization.Value;
|
||||
|
||||
if (pendingClient != null)
|
||||
{
|
||||
pendingClient.Connection.SetAccountInfo(new AccountInfo(senderSteamId, sentOwnerSteamId));
|
||||
ReadConnectionInitializationStep(
|
||||
pendingClient,
|
||||
new ReadWriteMessage(inc.Buffer, inc.BitPosition, inc.LengthBits, false),
|
||||
initializationStep);
|
||||
}
|
||||
else if (initializationStep == ConnectionInitialization.ConnectionStarted)
|
||||
{
|
||||
pendingClients.Add(new PendingClient(new SteamP2PConnection(senderSteamId)));
|
||||
}
|
||||
}
|
||||
else if (connectedClient != null)
|
||||
{
|
||||
var packet = INetSerializableStruct.Read<PeerPacketMessage>(inc);
|
||||
@@ -248,7 +248,7 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
if (!started) { return; }
|
||||
|
||||
if (!(conn is SteamP2PConnection steamP2PConn)) { return; }
|
||||
if (conn is not SteamP2PConnection steamP2PConn) { return; }
|
||||
|
||||
if (!connectedClients.Contains(steamP2PConn) && conn != OwnerConnection)
|
||||
{
|
||||
@@ -256,7 +256,7 @@ namespace Barotrauma.Networking
|
||||
return;
|
||||
}
|
||||
|
||||
if (!conn.AccountInfo.AccountId.TryUnwrap(out var connAccountId) || !(connAccountId is SteamId connSteamId)) { return; }
|
||||
if (!conn.AccountInfo.AccountId.TryUnwrap(out var connAccountId) || connAccountId is not SteamId) { return; }
|
||||
|
||||
byte[] bufAux = msg.PrepareForSending(compressPastThreshold, out bool isCompressed, out _);
|
||||
|
||||
@@ -292,9 +292,9 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
if (!started) { return; }
|
||||
|
||||
if (!(conn is SteamP2PConnection steamp2pConn)) { return; }
|
||||
if (conn is not SteamP2PConnection steamp2pConn) { return; }
|
||||
|
||||
if (!conn.AccountInfo.AccountId.TryUnwrap(out var connAccountId) || !(connAccountId is SteamId connSteamId)) { return; }
|
||||
if (!conn.AccountInfo.AccountId.TryUnwrap(out var connAccountId) || connAccountId is not SteamId connSteamId) { return; }
|
||||
|
||||
SendDisconnectMessage(connSteamId, peerDisconnectPacket);
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<RootNamespace>Barotrauma</RootNamespace>
|
||||
<Authors>FakeFish, Undertow Games</Authors>
|
||||
<Product>Barotrauma Dedicated Server</Product>
|
||||
<Version>0.19.5.0</Version>
|
||||
<Version>0.19.8.0</Version>
|
||||
<Copyright>Copyright © FakeFish 2018-2022</Copyright>
|
||||
<Platforms>AnyCPU;x64</Platforms>
|
||||
<AssemblyName>DedicatedServer</AssemblyName>
|
||||
|
||||
@@ -466,7 +466,12 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
}
|
||||
steeringManager.Update(Character.AnimController.GetCurrentSpeed(run && Character.CanRun));
|
||||
|
||||
//if someone is grabbing the bot and the bot isn't trying to run anywhere, let them keep dragging and "control" the bot
|
||||
if (Character.SelectedBy == null || run)
|
||||
{
|
||||
steeringManager.Update(Character.AnimController.GetCurrentSpeed(run && Character.CanRun));
|
||||
}
|
||||
|
||||
bool ignorePlatforms = Character.AnimController.TargetMovement.Y < -0.5f && (-Character.AnimController.TargetMovement.Y > Math.Abs(Character.AnimController.TargetMovement.X));
|
||||
if (steeringManager == insideSteering)
|
||||
|
||||
@@ -913,11 +913,14 @@ namespace Barotrauma
|
||||
|
||||
private void RemoveFollowTarget()
|
||||
{
|
||||
if (arrestingRegistered)
|
||||
if (followTargetObjective != null)
|
||||
{
|
||||
followTargetObjective.Completed -= OnArrestTargetReached;
|
||||
if (arrestingRegistered)
|
||||
{
|
||||
followTargetObjective.Completed -= OnArrestTargetReached;
|
||||
}
|
||||
RemoveSubObjective(ref followTargetObjective);
|
||||
}
|
||||
RemoveSubObjective(ref followTargetObjective);
|
||||
arrestingRegistered = false;
|
||||
}
|
||||
|
||||
|
||||
@@ -595,6 +595,10 @@ namespace Barotrauma
|
||||
{
|
||||
return c.CurrentHull;
|
||||
}
|
||||
else if (target is Structure structure)
|
||||
{
|
||||
return Hull.FindHull(structure.Position, useWorldCoordinates: false);
|
||||
}
|
||||
else if (target is Gap g)
|
||||
{
|
||||
return g.FlowTargetHull;
|
||||
|
||||
@@ -54,7 +54,7 @@ namespace Barotrauma
|
||||
if (ValidContainableItemIdentifiers.None())
|
||||
{
|
||||
#if DEBUG
|
||||
DebugConsole.ShowError($"No valid containable item identifiers found for the Load Item objective targeting {Container}");
|
||||
DebugConsole.LogError($"No valid containable item identifiers found for the Load Item objective targeting {Container}");
|
||||
#endif
|
||||
Abandon = true;
|
||||
return;
|
||||
@@ -250,7 +250,7 @@ namespace Barotrauma
|
||||
catch (NotImplementedException)
|
||||
{
|
||||
#if DEBUG
|
||||
DebugConsole.ShowError($"Unexpected target condition \"{TargetItemCondition}\" in local function GetConditionBasedProperty");
|
||||
DebugConsole.LogError($"Unexpected target condition \"{TargetItemCondition}\" in local function GetConditionBasedProperty");
|
||||
#endif
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
@@ -90,7 +90,7 @@ namespace Barotrauma
|
||||
catch (NotImplementedException)
|
||||
{
|
||||
#if DEBUG
|
||||
DebugConsole.ShowError($"Unexpected target condition \"{targetCondition}\" in AIObjectiveLoadItems.ItemMatchesTargetCondition");
|
||||
DebugConsole.LogError($"Unexpected target condition \"{targetCondition}\" in AIObjectiveLoadItems.ItemMatchesTargetCondition");
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -37,6 +37,8 @@ namespace Barotrauma
|
||||
public Func<bool> completionCondition;
|
||||
private bool isDoneOperating;
|
||||
|
||||
public float? OverridePriority = null;
|
||||
|
||||
protected override float GetPriority()
|
||||
{
|
||||
bool isOrder = objectiveManager.IsOrder(this);
|
||||
@@ -52,7 +54,11 @@ namespace Barotrauma
|
||||
}
|
||||
else
|
||||
{
|
||||
if (isOrder)
|
||||
if (OverridePriority.HasValue)
|
||||
{
|
||||
Priority = OverridePriority.Value;
|
||||
}
|
||||
else if (isOrder)
|
||||
{
|
||||
Priority = objectiveManager.GetOrderPriority(this);
|
||||
}
|
||||
@@ -135,7 +141,7 @@ namespace Barotrauma
|
||||
float value = CumulatedDevotion + (max * PriorityModifier);
|
||||
Priority = MathHelper.Clamp(value, 0, max);
|
||||
}
|
||||
else
|
||||
else if (!OverridePriority.HasValue)
|
||||
{
|
||||
float value = CumulatedDevotion + (AIObjectiveManager.LowestOrderPriority * PriorityModifier);
|
||||
float max = AIObjectiveManager.LowestOrderPriority - 1;
|
||||
@@ -204,8 +210,15 @@ namespace Barotrauma
|
||||
{
|
||||
if (!character.IsClimbing && character.CanInteractWith(target.Item, out _, checkLinked: false))
|
||||
{
|
||||
HumanAIController.FaceTarget(target.Item);
|
||||
if (character.SelectedItem != target.Item)
|
||||
if (target.Item.GetComponent<Controller>() is not Controller { ControlCharacterPose: true })
|
||||
{
|
||||
HumanAIController.FaceTarget(target.Item);
|
||||
}
|
||||
else
|
||||
{
|
||||
HumanAIController.SteeringManager.Reset();
|
||||
}
|
||||
if (character.SelectedItem != target.Item && character.SelectedSecondaryItem != target.Item)
|
||||
{
|
||||
target.Item.TryInteract(character, forceSelectKey: true);
|
||||
}
|
||||
|
||||
@@ -278,7 +278,7 @@ namespace Barotrauma
|
||||
float cprSuitability = targetCharacter.Oxygen < 0.0f ? -targetCharacter.Oxygen * 100.0f : 0.0f;
|
||||
|
||||
//find which treatments are the most suitable to treat the character's current condition
|
||||
targetCharacter.CharacterHealth.GetSuitableTreatments(currentTreatmentSuitabilities, normalize: false, predictFutureDuration: 10.0f);
|
||||
targetCharacter.CharacterHealth.GetSuitableTreatments(currentTreatmentSuitabilities, user: character, normalize: false, predictFutureDuration: 10.0f);
|
||||
|
||||
//check if we already have a suitable treatment for any of the afflictions
|
||||
foreach (Affliction affliction in GetSortedAfflictions(targetCharacter))
|
||||
|
||||
@@ -3,9 +3,8 @@ using Barotrauma.Items.Components;
|
||||
using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Xml.Linq;
|
||||
using System.Linq;
|
||||
using System.Collections.Immutable;
|
||||
using System.Linq;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
@@ -151,7 +150,7 @@ namespace Barotrauma
|
||||
public OrderPrefab(ContentXElement orderElement, OrdersFile file) : base(file, orderElement.GetAttributeIdentifier("identifier", ""))
|
||||
{
|
||||
Name = TextManager.Get($"OrderName.{Identifier}");
|
||||
ContextualName = TextManager.Get($"OrderNameContextual.{Identifier}");
|
||||
ContextualName = TextManager.Get($"OrderNameContextual.{Identifier}").Fallback(Name);
|
||||
|
||||
string targetItemType = orderElement.GetAttributeString("targetitemtype", "");
|
||||
if (!string.IsNullOrWhiteSpace(targetItemType))
|
||||
@@ -435,7 +434,7 @@ namespace Barotrauma
|
||||
}
|
||||
catch (NotImplementedException e)
|
||||
{
|
||||
DebugConsole.ShowError($"Error creating a new Order instance: unexpected target type \"{targetType}\".\n{e.StackTrace.CleanupStackTrace()}");
|
||||
DebugConsole.LogError($"Error creating a new Order instance: unexpected target type \"{targetType}\".\n{e.StackTrace.CleanupStackTrace()}");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -336,7 +336,7 @@ namespace Barotrauma
|
||||
{
|
||||
ApplyTestPose();
|
||||
}
|
||||
else
|
||||
else if (character.SelectedBy == null)
|
||||
{
|
||||
if (character.LockHands)
|
||||
{
|
||||
@@ -356,7 +356,7 @@ namespace Barotrauma
|
||||
HandIK(rightHand, midPos, CurrentAnimationParams.ArmIKStrength, CurrentAnimationParams.HandIKStrength);
|
||||
HandIK(leftHand, midPos, CurrentAnimationParams.ArmIKStrength, CurrentAnimationParams.HandIKStrength);
|
||||
}
|
||||
if (Anim != Animation.UsingItem && character.SelectedBy == null)
|
||||
if (Anim != Animation.UsingItem)
|
||||
{
|
||||
if (Anim != Animation.UsingItemWhileClimbing)
|
||||
{
|
||||
@@ -1716,8 +1716,16 @@ namespace Barotrauma
|
||||
}
|
||||
else if (target is AICharacter && target != Character.Controlled)
|
||||
{
|
||||
target.AnimController.TargetDir = WorldPosition.X > target.WorldPosition.X ? Direction.Right : Direction.Left;
|
||||
Vector2 movement = (character.SimPosition + Vector2.UnitX * 0.5f * Dir) - target.SimPosition;
|
||||
if (target.AnimController.Dir > 0 == WorldPosition.X > target.WorldPosition.X)
|
||||
{
|
||||
target.AnimController.LockFlippingUntil = (float)Timing.TotalTime + 0.5f;
|
||||
}
|
||||
else
|
||||
{
|
||||
target.AnimController.TargetDir = WorldPosition.X > target.WorldPosition.X ? Direction.Right : Direction.Left;
|
||||
}
|
||||
//make the target stand 0.5 meters away from this character, on the side they're currently at
|
||||
Vector2 movement = (character.SimPosition + Vector2.UnitX * 0.5f * Math.Sign(target.SimPosition.X - character.SimPosition.X)) - target.SimPosition;
|
||||
target.AnimController.TargetMovement = movement.LengthSquared() > 0.01f ? movement : Vector2.Zero;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -402,9 +402,8 @@ namespace Barotrauma
|
||||
}
|
||||
else
|
||||
{
|
||||
string afflictionIdentifier = subElement.GetAttributeString("identifier", "").ToLowerInvariant();
|
||||
afflictionPrefab = AfflictionPrefab.Prefabs[afflictionIdentifier];
|
||||
if (afflictionPrefab == null)
|
||||
Identifier afflictionIdentifier = subElement.GetAttributeIdentifier("identifier", "");
|
||||
if (!AfflictionPrefab.Prefabs.TryGet(afflictionIdentifier, out afflictionPrefab))
|
||||
{
|
||||
DebugConsole.ThrowError("Error in Attack (" + parentDebugName + ") - Affliction prefab \"" + afflictionIdentifier + "\" not found.");
|
||||
continue;
|
||||
@@ -430,15 +429,13 @@ namespace Barotrauma
|
||||
Afflictions.Clear();
|
||||
foreach (var subElement in element.GetChildElements("affliction"))
|
||||
{
|
||||
AfflictionPrefab afflictionPrefab;
|
||||
Affliction affliction;
|
||||
Identifier afflictionIdentifier = subElement.GetAttributeIdentifier("identifier", "");
|
||||
if (!AfflictionPrefab.Prefabs.ContainsKey(afflictionIdentifier))
|
||||
if (!AfflictionPrefab.Prefabs.TryGet(afflictionIdentifier, out AfflictionPrefab afflictionPrefab))
|
||||
{
|
||||
DebugConsole.ThrowError($"Error in an Attack defined in \"{parentDebugName}\" - could not find an affliction with the identifier \"{afflictionIdentifier}\".");
|
||||
continue;
|
||||
}
|
||||
afflictionPrefab = AfflictionPrefab.Prefabs[afflictionIdentifier];
|
||||
affliction = afflictionPrefab.Instantiate(0.0f);
|
||||
affliction.Deserialize(subElement);
|
||||
//backwards compatibility
|
||||
|
||||
@@ -549,6 +549,10 @@ namespace Barotrauma
|
||||
set
|
||||
{
|
||||
lockHandsTimer = MathHelper.Clamp(lockHandsTimer + (value ? 1.0f : -0.5f), 0.0f, 10.0f);
|
||||
if (value)
|
||||
{
|
||||
SelectedCharacter = null;
|
||||
}
|
||||
#if CLIENT
|
||||
HintManager.OnHandcuffed(this);
|
||||
#endif
|
||||
@@ -599,13 +603,10 @@ namespace Barotrauma
|
||||
get { return selectedCharacter; }
|
||||
set
|
||||
{
|
||||
if (value == selectedCharacter) return;
|
||||
if (selectedCharacter != null)
|
||||
selectedCharacter.selectedBy = null;
|
||||
if (value == selectedCharacter) { return; }
|
||||
if (selectedCharacter != null) { selectedCharacter.selectedBy = null; }
|
||||
selectedCharacter = value;
|
||||
if (selectedCharacter != null)
|
||||
selectedCharacter.selectedBy = this;
|
||||
|
||||
if (selectedCharacter != null) {selectedCharacter.selectedBy = this; }
|
||||
#if CLIENT
|
||||
CharacterHealth.SetHealthBarVisibility(value == null);
|
||||
#endif
|
||||
@@ -707,6 +708,14 @@ namespace Barotrauma
|
||||
get { return CurrentHull == null || CurrentHull.LethalPressure > 5.0f; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Can be used by status effects
|
||||
/// </summary>
|
||||
public AnimController.Animation Anim
|
||||
{
|
||||
get { return AnimController?.Anim ?? AnimController.Animation.None; }
|
||||
}
|
||||
|
||||
public const float KnockbackCooldown = 5.0f;
|
||||
public float KnockbackCooldownTimer;
|
||||
|
||||
@@ -2620,7 +2629,7 @@ namespace Barotrauma
|
||||
if (!AllowInput)
|
||||
{
|
||||
FocusedCharacter = null;
|
||||
if (SelectedCharacter != null) DeselectCharacter();
|
||||
if (SelectedCharacter != null) { DeselectCharacter(); }
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -3636,7 +3645,7 @@ namespace Barotrauma
|
||||
string modifiedMessage = ChatMessage.ApplyDistanceEffect(message.Message, message.MessageType.Value, this, Controlled);
|
||||
if (!string.IsNullOrEmpty(modifiedMessage))
|
||||
{
|
||||
GameMain.GameSession.CrewManager.AddSinglePlayerChatMessage(info.Name, modifiedMessage, message.MessageType.Value, this);
|
||||
GameMain.GameSession.CrewManager.AddSinglePlayerChatMessage(Name, modifiedMessage, message.MessageType.Value, this);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -4020,6 +4029,7 @@ namespace Barotrauma
|
||||
if (newStun > 0.0f)
|
||||
{
|
||||
SelectedItem = SelectedSecondaryItem = null;
|
||||
if (SelectedCharacter != null) { DeselectCharacter(); }
|
||||
}
|
||||
HealthUpdateInterval = 0.0f;
|
||||
}
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using Barotrauma.Items.Components;
|
||||
using Barotrauma.Networking;
|
||||
using Barotrauma.Networking;
|
||||
using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Linq;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
@@ -25,9 +26,10 @@ namespace Barotrauma
|
||||
UpdateSkills = 12,
|
||||
UpdateMoney = 13,
|
||||
UpdatePermanentStats = 14,
|
||||
RemoveFromCrew = 15,
|
||||
|
||||
MinValue = 0,
|
||||
MaxValue = 14
|
||||
MaxValue = 15
|
||||
}
|
||||
|
||||
private interface IEventData : NetEntityEvent.IData
|
||||
@@ -133,18 +135,30 @@ namespace Barotrauma
|
||||
public EventType EventType => EventType.TeamChange;
|
||||
}
|
||||
|
||||
[NetworkSerialize]
|
||||
public readonly record struct ItemTeamChange(CharacterTeamType TeamId, ImmutableArray<UInt16> ItemIds) : INetSerializableStruct;
|
||||
|
||||
|
||||
public struct AddToCrewEventData : IEventData
|
||||
{
|
||||
public EventType EventType => EventType.AddToCrew;
|
||||
public readonly CharacterTeamType TeamType;
|
||||
public readonly ImmutableArray<Item> InventoryItems;
|
||||
public readonly ItemTeamChange ItemTeamChange;
|
||||
|
||||
public AddToCrewEventData(CharacterTeamType teamType, IEnumerable<Item> inventoryItems)
|
||||
{
|
||||
TeamType = teamType;
|
||||
InventoryItems = inventoryItems.ToImmutableArray();
|
||||
ItemTeamChange = new ItemTeamChange(teamType, inventoryItems.Select(it => it.ID).ToImmutableArray());
|
||||
}
|
||||
}
|
||||
|
||||
public struct RemoveFromCrewEventData : IEventData
|
||||
{
|
||||
public EventType EventType => EventType.RemoveFromCrew;
|
||||
public readonly ItemTeamChange ItemTeamChange;
|
||||
|
||||
public RemoveFromCrewEventData(CharacterTeamType teamType, IEnumerable<Item> inventoryItems)
|
||||
{
|
||||
ItemTeamChange = new ItemTeamChange(teamType, inventoryItems.Select(it => it.ID).ToImmutableArray());
|
||||
}
|
||||
}
|
||||
|
||||
public struct UpdateExperienceEventData : IEventData
|
||||
|
||||
@@ -82,10 +82,10 @@ namespace Barotrauma
|
||||
public UInt16 networkUpdateID;
|
||||
}
|
||||
|
||||
private List<NetInputMem> memInput = new List<NetInputMem>();
|
||||
private readonly List<NetInputMem> memInput = new List<NetInputMem>();
|
||||
|
||||
private List<CharacterStateInfo> memState = new List<CharacterStateInfo>();
|
||||
private List<CharacterStateInfo> memLocalState = new List<CharacterStateInfo>();
|
||||
private readonly List<CharacterStateInfo> memState = new List<CharacterStateInfo>();
|
||||
private readonly List<CharacterStateInfo> memLocalState = new List<CharacterStateInfo>();
|
||||
|
||||
public float healthUpdateTimer;
|
||||
|
||||
|
||||
@@ -1038,7 +1038,7 @@ namespace Barotrauma
|
||||
/// <param name="treatmentSuitability">A dictionary where the key is the identifier of the item and the value the suitability</param>
|
||||
/// <param name="normalize">If true, the suitability values are normalized between 0 and 1. If not, they're arbitrary values defined in the medical item XML, where negative values are unsuitable, and positive ones suitable.</param>
|
||||
/// <param name="predictFutureDuration">If above 0, the method will take into account how much currently active status effects while affect the afflictions in the next x seconds.</param>
|
||||
public void GetSuitableTreatments(Dictionary<Identifier, float> treatmentSuitability, bool normalize, Limb limb = null, bool ignoreHiddenAfflictions = false, float predictFutureDuration = 0.0f)
|
||||
public void GetSuitableTreatments(Dictionary<Identifier, float> treatmentSuitability, bool normalize, Character user, Limb limb = null, bool ignoreHiddenAfflictions = false, float predictFutureDuration = 0.0f)
|
||||
{
|
||||
//key = item identifier
|
||||
//float = suitability
|
||||
@@ -1062,7 +1062,18 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
if (strength <= affliction.Prefab.TreatmentThreshold) { continue; }
|
||||
if (ignoreHiddenAfflictions && strength < affliction.Prefab.ShowIconThreshold) { continue; }
|
||||
|
||||
if (ignoreHiddenAfflictions)
|
||||
{
|
||||
if (user == Character)
|
||||
{
|
||||
if (strength < affliction.Prefab.ShowIconThreshold) { continue; }
|
||||
}
|
||||
else
|
||||
{
|
||||
if (strength < affliction.Prefab.ShowIconToOthersThreshold) { continue; }
|
||||
}
|
||||
}
|
||||
|
||||
foreach (KeyValuePair<Identifier, float> treatment in affliction.Prefab.TreatmentSuitability)
|
||||
{
|
||||
@@ -1153,10 +1164,10 @@ namespace Barotrauma
|
||||
msg.WriteRangedSingle(
|
||||
MathHelper.Clamp(affliction.Strength, 0.0f, affliction.Prefab.MaxStrength),
|
||||
0.0f, affliction.Prefab.MaxStrength, 8);
|
||||
msg.WriteByte((byte)affliction.Prefab.PeriodicEffects.Count());
|
||||
msg.WriteByte((byte)affliction.Prefab.PeriodicEffects.Count);
|
||||
foreach (AfflictionPrefab.PeriodicEffect periodicEffect in affliction.Prefab.PeriodicEffects)
|
||||
{
|
||||
msg.WriteRangedSingle(affliction.PeriodicEffectTimers[periodicEffect], periodicEffect.MinInterval, periodicEffect.MaxInterval, 8);
|
||||
msg.WriteRangedSingle(affliction.PeriodicEffectTimers[periodicEffect], 0, periodicEffect.MaxInterval, 8);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1178,7 +1189,7 @@ namespace Barotrauma
|
||||
msg.WriteRangedSingle(
|
||||
MathHelper.Clamp(affliction.Strength, 0.0f, affliction.Prefab.MaxStrength),
|
||||
0.0f, affliction.Prefab.MaxStrength, 8);
|
||||
msg.WriteByte((byte)affliction.Prefab.PeriodicEffects.Count());
|
||||
msg.WriteByte((byte)affliction.Prefab.PeriodicEffects.Count);
|
||||
foreach (AfflictionPrefab.PeriodicEffect periodicEffect in affliction.Prefab.PeriodicEffects)
|
||||
{
|
||||
msg.WriteRangedSingle(affliction.PeriodicEffectTimers[periodicEffect], periodicEffect.MinInterval, periodicEffect.MaxInterval, 8);
|
||||
|
||||
@@ -86,6 +86,28 @@ namespace Barotrauma
|
||||
{
|
||||
DebugConsole.ThrowError("Error in DamageModifier config (" + parentDebugName + ") - define afflictions using identifiers or types instead of names.");
|
||||
}
|
||||
foreach (var afflictionType in parsedAfflictionTypes)
|
||||
{
|
||||
if (!AfflictionPrefab.Prefabs.Any(p => p.AfflictionType == afflictionType))
|
||||
{
|
||||
createWarningOrError($"Potentially invalid damage modifier in \"{parentDebugName}\". Could not find any afflictions of the type \"{afflictionType}\". Did you mean to use an affliction identifier instead?");
|
||||
}
|
||||
}
|
||||
foreach (var afflictionIdentifier in parsedAfflictionIdentifiers)
|
||||
{
|
||||
if (!AfflictionPrefab.Prefabs.ContainsKey(afflictionIdentifier))
|
||||
{
|
||||
createWarningOrError($"Potentially invalid damage modifier in \"{parentDebugName}\". Could not find any afflictions with the identifier \"{afflictionIdentifier}\". Did you mean to use an affliction type instead?");
|
||||
}
|
||||
}
|
||||
static void createWarningOrError(string msg)
|
||||
{
|
||||
#if DEBUG
|
||||
DebugConsole.ThrowError(msg);
|
||||
#else
|
||||
DebugConsole.AddWarning(msg);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
private void ParseAfflictionTypes()
|
||||
|
||||
@@ -1,8 +1,4 @@
|
||||
using Barotrauma.Items.Components;
|
||||
using Microsoft.Xna.Framework;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
using Microsoft.Xna.Framework;
|
||||
|
||||
namespace Barotrauma.Abilities
|
||||
{
|
||||
@@ -31,7 +27,7 @@ namespace Barotrauma.Abilities
|
||||
}
|
||||
}
|
||||
|
||||
if (!SelectedItemHasTag(closestCharacter)) { return; }
|
||||
if (closestCharacter == null || !SelectedItemHasTag(closestCharacter)) { return; }
|
||||
|
||||
if (closestDistance < squaredMaxDistance)
|
||||
{
|
||||
|
||||
@@ -1267,7 +1267,11 @@ namespace Barotrauma
|
||||
}
|
||||
}, () =>
|
||||
{
|
||||
return new[] { FactionPrefab.Prefabs.Select(f => f.Identifier.Value).ToArray() };
|
||||
return new[]
|
||||
{
|
||||
FactionPrefab.Prefabs.Select(f => f.Identifier.Value).ToArray(),
|
||||
GameMain.GameSession?.Campaign.Factions.Select(f => f.Prefab.Identifier.ToString()).ToArray() ?? Array.Empty<string>()
|
||||
};
|
||||
}, true));
|
||||
|
||||
commands.Add(new Command("fixitems", "fixitems: Repairs all items and restores them to full condition.", (string[] args) =>
|
||||
@@ -2235,7 +2239,7 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
public static void ShowError(string msg, Color? color = null)
|
||||
public static void LogError(string msg, Color? color = null)
|
||||
{
|
||||
color ??= Color.Red;
|
||||
NewMessage(msg, color.Value, isCommand: false, isError: true);
|
||||
@@ -2407,7 +2411,7 @@ namespace Barotrauma
|
||||
}
|
||||
#endif
|
||||
|
||||
ShowError(error);
|
||||
LogError(error);
|
||||
}
|
||||
|
||||
public static void AddWarning(string warning)
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
|
||||
@@ -38,10 +38,12 @@ namespace Barotrauma
|
||||
}
|
||||
IEnumerable<Affliction> afflictions = target.CharacterHealth.GetAllAfflictions().Where(affliction =>
|
||||
{
|
||||
LimbType? limbType = target.CharacterHealth.GetAfflictionLimb(affliction)?.type;
|
||||
if (limbType == null) { return false; }
|
||||
|
||||
return limbType == TargetLimb && affliction.Strength >= MinStrength;
|
||||
if (affliction.Prefab.LimbSpecific)
|
||||
{
|
||||
LimbType? limbType = target.CharacterHealth.GetAfflictionLimb(affliction)?.type;
|
||||
if (limbType == null || limbType != TargetLimb) { return false; }
|
||||
}
|
||||
return affliction.Strength >= MinStrength;
|
||||
});
|
||||
|
||||
if (afflictions.Any(a => a.Identifier == Identifier)) { return true; }
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace Barotrauma
|
||||
{
|
||||
if (TargetTag.IsEmpty)
|
||||
{
|
||||
DebugConsole.ShowError($"CheckConditionalAction error: {GetEventName()} uses a CheckConditionalAction with no target tag! This will cause the check to automatically succeed.");
|
||||
DebugConsole.LogError($"CheckConditionalAction error: {GetEventName()} uses a CheckConditionalAction with no target tag! This will cause the check to automatically succeed.");
|
||||
}
|
||||
foreach (var attribute in element.Attributes())
|
||||
{
|
||||
@@ -25,7 +25,7 @@ namespace Barotrauma
|
||||
}
|
||||
if (Conditional == null)
|
||||
{
|
||||
DebugConsole.ShowError($"CheckConditionalAction error: {GetEventName()} uses a CheckConditionalAction with no valid PropertyConditional! This will cause the check to automatically succeed.");
|
||||
DebugConsole.LogError($"CheckConditionalAction error: {GetEventName()} uses a CheckConditionalAction with no valid PropertyConditional! This will cause the check to automatically succeed.");
|
||||
}
|
||||
|
||||
static bool IsTargetTagAttribute(XAttribute attribute) => attribute.NameAsIdentifier() == "targettag";
|
||||
@@ -52,7 +52,7 @@ namespace Barotrauma
|
||||
}
|
||||
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.");
|
||||
DebugConsole.LogError($"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)
|
||||
{
|
||||
|
||||
@@ -18,10 +18,14 @@ class CheckConnectionAction : BinaryOptionAction
|
||||
[Serialize("", IsPropertySaveable.Yes)]
|
||||
public Identifier OtherConnectionName { get; set; }
|
||||
|
||||
[Serialize(1, IsPropertySaveable.Yes)]
|
||||
public int MinAmount { get; set; }
|
||||
|
||||
public CheckConnectionAction(ScriptedEvent parentEvent, ContentXElement element) : base(parentEvent, element) { }
|
||||
|
||||
protected override bool? DetermineSuccess()
|
||||
{
|
||||
int amount = 0;
|
||||
var connectTargets = !ConnectedItemTag.IsEmpty ? ParentEvent.GetTargets(ConnectedItemTag) : Enumerable.Empty<Entity>();
|
||||
foreach (var target in ParentEvent.GetTargets(ItemTag))
|
||||
{
|
||||
@@ -33,27 +37,17 @@ class CheckConnectionAction : BinaryOptionAction
|
||||
if (!IsCorrectConnection(connection, ConnectionName)) { continue; }
|
||||
if (ConnectedItemTag.IsEmpty && OtherConnectionName.IsEmpty)
|
||||
{
|
||||
if (connection.Wires.Any()) { return true; }
|
||||
amount += connection.Wires.Count();
|
||||
if (amount >= MinAmount) { return true; }
|
||||
continue;
|
||||
}
|
||||
foreach (var wire in connection.Wires)
|
||||
{
|
||||
if (wire.OtherConnection(connection) is not Connection otherConnection) { continue; }
|
||||
if (ConnectedItemTag.IsEmpty)
|
||||
{
|
||||
if (IsCorrectConnection(otherConnection, OtherConnectionName)) { return true; }
|
||||
}
|
||||
else if (OtherConnectionName.IsEmpty)
|
||||
{
|
||||
if (IsCorrectItem()) { return true; }
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!IsCorrectConnection(otherConnection, OtherConnectionName)) { continue; }
|
||||
if (!IsCorrectItem()) { continue; }
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!ConnectedItemTag.IsEmpty && !IsCorrectConnection(otherConnection, OtherConnectionName)) { continue; }
|
||||
if (!ConnectedItemTag.IsEmpty && !IsCorrectItem()) { continue; }
|
||||
amount++;
|
||||
if (amount >= MinAmount) { return true; }
|
||||
bool IsCorrectItem() => connectTargets.Contains(otherConnection.Item);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#nullable enable
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
@@ -36,15 +35,32 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
public CheckDataAction(ContentXElement element, string parentDebugString) : base(null, element)
|
||||
{
|
||||
if (string.IsNullOrEmpty(Condition))
|
||||
{
|
||||
Condition = element.GetAttributeString("value", string.Empty)!;
|
||||
if (string.IsNullOrEmpty(Condition))
|
||||
{
|
||||
DebugConsole.ThrowError($"Error in scripted event \"{parentDebugString}\". CheckDataAction with no condition set ({element}).");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool GetSuccess()
|
||||
{
|
||||
return DetermineSuccess() ?? false;
|
||||
}
|
||||
|
||||
protected override bool? DetermineSuccess()
|
||||
{
|
||||
if (!(GameMain.GameSession?.GameMode is CampaignMode campaignMode)) { return false; }
|
||||
if (GameMain.GameSession?.GameMode is not CampaignMode campaignMode) { return false; }
|
||||
|
||||
string[] splitString = Condition.Split(' ');
|
||||
string value = Condition;
|
||||
string value;
|
||||
if (splitString.Length > 0)
|
||||
{
|
||||
#warning Is this correct?
|
||||
//the first part of the string is the operator, skip it
|
||||
value = string.Join(" ", splitString.Skip(1));
|
||||
}
|
||||
else
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using Barotrauma.Items.Components;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
|
||||
@@ -15,9 +16,20 @@ namespace Barotrauma
|
||||
[Serialize("", IsPropertySaveable.Yes)]
|
||||
public string ItemTags { get; set; }
|
||||
|
||||
[Serialize(1, IsPropertySaveable.Yes)]
|
||||
public int Amount { get; set; }
|
||||
|
||||
[Serialize("", IsPropertySaveable.Yes, description: "Tag to apply to the first target when the check succeeds.")]
|
||||
public Identifier ApplyTagToTarget { get; set; }
|
||||
|
||||
[Serialize(false, IsPropertySaveable.Yes)]
|
||||
public bool RequireEquipped { get; set; }
|
||||
|
||||
[Serialize(-1, IsPropertySaveable.Yes)]
|
||||
public int ItemContainerIndex { get; set; }
|
||||
|
||||
private readonly IReadOnlyList<PropertyConditional> conditionals;
|
||||
|
||||
private readonly Identifier[] itemIdentifierSplit;
|
||||
private readonly Identifier[] itemTags;
|
||||
|
||||
@@ -25,6 +37,19 @@ namespace Barotrauma
|
||||
{
|
||||
itemIdentifierSplit = ItemIdentifiers.Split(',').ToIdentifiers();
|
||||
itemTags = ItemTags.Split(",").ToIdentifiers();
|
||||
var conditionalList = new List<PropertyConditional>();
|
||||
foreach (ContentXElement subElement in element.GetChildElements("conditional"))
|
||||
{
|
||||
foreach (XAttribute attribute in subElement.Attributes())
|
||||
{
|
||||
if (PropertyConditional.IsValid(attribute))
|
||||
{
|
||||
conditionalList.Add(new PropertyConditional(attribute));
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
conditionals = conditionalList;
|
||||
}
|
||||
|
||||
protected override bool? DetermineSuccess()
|
||||
@@ -35,25 +60,70 @@ namespace Barotrauma
|
||||
{
|
||||
if (target is Character character)
|
||||
{
|
||||
if (RequireEquipped)
|
||||
Inventory inventory = character.Inventory;
|
||||
if (CheckInventory(character.Inventory, character))
|
||||
{
|
||||
if (itemTags.Any(tag => character.HasEquippedItem(tag))) { return true; }
|
||||
if (itemIdentifierSplit.Any(identifier => character.HasEquippedItem(identifier))) { return true; }
|
||||
return false;
|
||||
if (!ApplyTagToTarget.IsEmpty)
|
||||
{
|
||||
ParentEvent.AddTarget(ApplyTagToTarget, target);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (character.Inventory is not CharacterInventory inventory) { continue; }
|
||||
if (itemTags.Any(tag => inventory.FindItemByTag(tag, recursive: true) is not null)) { return true; }
|
||||
if (itemIdentifierSplit.Any(identifier => inventory.FindItemByIdentifier(identifier, recursive: true) is not null)) { return true; }
|
||||
}
|
||||
else if (target is Item item && item.OwnInventory is ItemInventory inventory)
|
||||
else if (target is Item item)
|
||||
{
|
||||
if (itemTags.Any(tag => inventory.FindItemByTag(tag, recursive: true) is not null)) { return true; }
|
||||
if (itemIdentifierSplit.Any(identifier => inventory.FindItemByIdentifier(identifier, recursive: true) is not null)) { return true; }
|
||||
int i = 0;
|
||||
foreach (var itemContainer in item.GetComponents<ItemContainer>())
|
||||
{
|
||||
if (ItemContainerIndex == -1 || i == ItemContainerIndex)
|
||||
{
|
||||
if (CheckInventory(itemContainer.Inventory, character: null))
|
||||
{
|
||||
if (!ApplyTagToTarget.IsEmpty)
|
||||
{
|
||||
ParentEvent.AddTarget(ApplyTagToTarget, target);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool CheckInventory(Inventory inventory, Character character)
|
||||
{
|
||||
if (inventory == null) { return false; }
|
||||
int count = 0;
|
||||
foreach (Item item in inventory.FindAllItems(it => itemTags.Any(it.HasTag) || itemIdentifierSplit.Contains(it.Prefab.Identifier)))
|
||||
{
|
||||
if (!ConditionalsMatch(item, character)) { continue; }
|
||||
count++;
|
||||
if (count >= Amount) { return true; }
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool ConditionalsMatch(Item item, Character character = null)
|
||||
{
|
||||
if (item == null) { return false; }
|
||||
foreach (PropertyConditional conditional in conditionals)
|
||||
{
|
||||
if (!conditional.Matches(item))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (RequireEquipped)
|
||||
{
|
||||
if (character == null) { return false; }
|
||||
return character.HasEquippedItem(item);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public override string ToDebugString()
|
||||
{
|
||||
return $"{ToolBox.GetDebugSymbol(HasBeenDetermined())} {nameof(CheckItemAction)} -> (TargetTag: {TargetTag.ColorizeObject()}, " +
|
||||
|
||||
@@ -11,6 +11,9 @@ namespace Barotrauma
|
||||
[Serialize("", IsPropertySaveable.Yes)]
|
||||
public Identifier OrderOption { get; set; }
|
||||
|
||||
[Serialize("", IsPropertySaveable.Yes)]
|
||||
public Identifier OrderTargetTag { get; set; }
|
||||
|
||||
public CheckOrderAction(ScriptedEvent parentEvent, ContentXElement element) : base(parentEvent, element) { }
|
||||
|
||||
protected override bool? DetermineSuccess()
|
||||
@@ -29,20 +32,17 @@ namespace Barotrauma
|
||||
}
|
||||
if (targetCharacter == null)
|
||||
{
|
||||
DebugConsole.ShowError($"CheckConditionalAction error: {GetEventName()} uses a CheckOrderAction but no valid target character was found for tag \"{TargetTag}\"! This will cause the check to automatically fail.");
|
||||
DebugConsole.LogError($"CheckConditionalAction error: {GetEventName()} uses a CheckOrderAction but no valid target character was found for tag \"{TargetTag}\"! This will cause the check to automatically fail.");
|
||||
return false;
|
||||
}
|
||||
var currentOrderInfo = targetCharacter.GetCurrentOrderWithTopPriority();
|
||||
if (currentOrderInfo?.Identifier == OrderIdentifier)
|
||||
{
|
||||
if (OrderOption.IsEmpty)
|
||||
if (!OrderTargetTag.IsEmpty)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return currentOrderInfo?.Option == OrderOption;
|
||||
if (currentOrderInfo.TargetEntity is not Item targetItem || !targetItem.HasTag(OrderTargetTag)) { return false; }
|
||||
}
|
||||
return OrderOption.IsEmpty || currentOrderInfo?.Option == OrderOption;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
using Barotrauma.Extensions;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
class CheckSelectedItemAction : BinaryOptionAction
|
||||
{
|
||||
public enum SelectedItemType { Primary, Secondary, Any };
|
||||
|
||||
[Serialize("", IsPropertySaveable.Yes)]
|
||||
public Identifier CharacterTag { get; set; }
|
||||
|
||||
[Serialize("", IsPropertySaveable.Yes)]
|
||||
public Identifier TargetTag { get; set; }
|
||||
|
||||
[Serialize(SelectedItemType.Any, IsPropertySaveable.Yes)]
|
||||
public SelectedItemType ItemType { get; set; }
|
||||
|
||||
public CheckSelectedItemAction(ScriptedEvent parentEvent, ContentXElement element) : base(parentEvent, element) { }
|
||||
|
||||
protected override bool? DetermineSuccess()
|
||||
{
|
||||
Character character = null;
|
||||
if (!CharacterTag.IsEmpty)
|
||||
{
|
||||
foreach (var t in ParentEvent.GetTargets(CharacterTag))
|
||||
{
|
||||
if (t is Character c)
|
||||
{
|
||||
character = c;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (character == null)
|
||||
{
|
||||
DebugConsole.LogError($"CheckSelectedItemAction error: {GetEventName()} uses a CheckSelectedItemAction but no valid character was found for tag \"{CharacterTag}\"! This will cause the check to automatically fail.");
|
||||
return false;
|
||||
}
|
||||
if (!TargetTag.IsEmpty)
|
||||
{
|
||||
IEnumerable<Entity> targets = ParentEvent.GetTargets(TargetTag);
|
||||
if (targets.None())
|
||||
{
|
||||
DebugConsole.LogError($"CheckSelectedItemAction error: {GetEventName()} uses a CheckSelectedItemAction but no valid targets were found for tag \"{TargetTag}\"! This will cause the check to automatically fail.");
|
||||
return false;
|
||||
}
|
||||
foreach (var target in targets)
|
||||
{
|
||||
if (target is not Item targetItem)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (IsSelected(targetItem))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
||||
bool IsSelected(Item item)
|
||||
{
|
||||
return ItemType switch
|
||||
{
|
||||
SelectedItemType.Any => character.IsAnySelectedItem(item),
|
||||
SelectedItemType.Primary => character.SelectedItem == item,
|
||||
SelectedItemType.Secondary => character.SelectedSecondaryItem == item,
|
||||
_ => false
|
||||
};
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return ItemType switch
|
||||
{
|
||||
SelectedItemType.Any => !character.HasSelectedAnyItem,
|
||||
SelectedItemType.Primary => character.SelectedItem == null,
|
||||
SelectedItemType.Secondary => character.SelectedSecondaryItem == null,
|
||||
_ => false
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private string GetEventName()
|
||||
{
|
||||
return ParentEvent?.Prefab?.Identifier is { IsEmpty: false } identifier ? $"the event \"{identifier}\"" : "an unknown event";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@ using System.Collections.Generic;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
class CheckSelectedItemAction : BinaryOptionAction
|
||||
class CheckSelectedAction : BinaryOptionAction
|
||||
{
|
||||
public enum SelectedItemType { Primary, Secondary, Any };
|
||||
|
||||
@@ -16,7 +16,7 @@ namespace Barotrauma
|
||||
[Serialize(SelectedItemType.Any, IsPropertySaveable.Yes)]
|
||||
public SelectedItemType ItemType { get; set; }
|
||||
|
||||
public CheckSelectedItemAction(ScriptedEvent parentEvent, ContentXElement element) : base(parentEvent, element) { }
|
||||
public CheckSelectedAction(ScriptedEvent parentEvent, ContentXElement element) : base(parentEvent, element) { }
|
||||
|
||||
protected override bool? DetermineSuccess()
|
||||
{
|
||||
@@ -34,7 +34,7 @@ namespace Barotrauma
|
||||
}
|
||||
if (character == null)
|
||||
{
|
||||
DebugConsole.ShowError($"CheckSelectedItemAction error: {GetEventName()} uses a CheckSelectedItemAction but no valid character was found for tag \"{CharacterTag}\"! This will cause the check to automatically fail.");
|
||||
DebugConsole.LogError($"CheckSelectedItemAction error: {GetEventName()} uses a CheckSelectedItemAction but no valid character was found for tag \"{CharacterTag}\"! This will cause the check to automatically fail.");
|
||||
return false;
|
||||
}
|
||||
if (!TargetTag.IsEmpty)
|
||||
@@ -42,11 +42,16 @@ namespace Barotrauma
|
||||
IEnumerable<Entity> targets = ParentEvent.GetTargets(TargetTag);
|
||||
if (targets.None())
|
||||
{
|
||||
DebugConsole.ShowError($"CheckSelectedItemAction error: {GetEventName()} uses a CheckSelectedItemAction but no valid targets were found for tag \"{TargetTag}\"! This will cause the check to automatically fail.");
|
||||
DebugConsole.LogError($"CheckSelectedItemAction error: {GetEventName()} uses a CheckSelectedItemAction but no valid targets were found for tag \"{TargetTag}\"! This will cause the check to automatically fail.");
|
||||
return false;
|
||||
}
|
||||
foreach (var target in targets)
|
||||
{
|
||||
if (target is Character targetCharacter)
|
||||
{
|
||||
if (ItemType == SelectedItemType.Any && character.SelectedCharacter == targetCharacter) { return true; }
|
||||
continue;
|
||||
}
|
||||
if (target is not Item targetItem)
|
||||
{
|
||||
continue;
|
||||
|
||||
@@ -134,7 +134,7 @@ namespace Barotrauma
|
||||
|
||||
public static EventAction Instantiate(ScriptedEvent scriptedEvent, ContentXElement element)
|
||||
{
|
||||
Type actionType = null;
|
||||
Type actionType;
|
||||
try
|
||||
{
|
||||
actionType = Type.GetType("Barotrauma." + element.Name, true, true);
|
||||
|
||||
@@ -1,8 +1,3 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
class GodModeAction : EventAction
|
||||
@@ -10,6 +5,9 @@ namespace Barotrauma
|
||||
[Serialize(true, IsPropertySaveable.Yes)]
|
||||
public bool Enabled { get; set; }
|
||||
|
||||
[Serialize(false, IsPropertySaveable.Yes, description: "Should the character's active afflictions be updated (e.g. applying visual effects of the afflictions)")]
|
||||
public bool UpdateAfflictions { get; set; }
|
||||
|
||||
[Serialize("", IsPropertySaveable.Yes)]
|
||||
public Identifier TargetTag { get; set; }
|
||||
|
||||
@@ -35,7 +33,14 @@ namespace Barotrauma
|
||||
{
|
||||
if (target != null && target is Character character)
|
||||
{
|
||||
character.GodMode = Enabled;
|
||||
if (UpdateAfflictions)
|
||||
{
|
||||
character.CharacterHealth.Unkillable = Enabled;
|
||||
}
|
||||
else
|
||||
{
|
||||
character.GodMode = Enabled;
|
||||
}
|
||||
}
|
||||
}
|
||||
isFinished = true;
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
namespace Barotrauma;
|
||||
|
||||
partial class InventoryHighlightAction : EventAction
|
||||
{
|
||||
[Serialize("", IsPropertySaveable.Yes)]
|
||||
public Identifier TargetTag { get; set; }
|
||||
|
||||
[Serialize("", IsPropertySaveable.Yes)]
|
||||
public Identifier ItemIdentifier { get; set; }
|
||||
|
||||
[Serialize(-1, IsPropertySaveable.Yes)]
|
||||
public int ItemContainerIndex { get; set; }
|
||||
|
||||
[Serialize(false, IsPropertySaveable.Yes)]
|
||||
public bool Recursive { get; set; }
|
||||
|
||||
private bool isFinished;
|
||||
|
||||
public InventoryHighlightAction(ScriptedEvent parentEvent, ContentXElement element) : base(parentEvent, element) { }
|
||||
|
||||
public override void Update(float deltaTime)
|
||||
{
|
||||
if (isFinished) { return; }
|
||||
UpdateProjSpecific();
|
||||
isFinished = true;
|
||||
}
|
||||
|
||||
partial void UpdateProjSpecific();
|
||||
|
||||
public override bool IsFinished(ref string goToLabel) => isFinished;
|
||||
|
||||
public override void Reset() => isFinished = false;
|
||||
}
|
||||
@@ -2,7 +2,7 @@ namespace Barotrauma
|
||||
{
|
||||
partial class MessageBoxAction : EventAction
|
||||
{
|
||||
public enum ActionType { Create, Close }
|
||||
public enum ActionType { Create, ConnectObjective, Close, Clear }
|
||||
|
||||
[Serialize(ActionType.Create, IsPropertySaveable.Yes)]
|
||||
public ActionType Type { get; set; }
|
||||
@@ -51,7 +51,13 @@ namespace Barotrauma
|
||||
|
||||
private bool isFinished = false;
|
||||
|
||||
public MessageBoxAction(ScriptedEvent parentEvent, ContentXElement element) : base(parentEvent, element) { }
|
||||
public MessageBoxAction(ScriptedEvent parentEvent, ContentXElement element) : base(parentEvent, element)
|
||||
{
|
||||
if (Identifier.IsEmpty)
|
||||
{
|
||||
Identifier = element.GetAttributeIdentifier("id", Identifier.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
public override void Update(float deltaTime)
|
||||
{
|
||||
|
||||
@@ -55,7 +55,7 @@ namespace Barotrauma
|
||||
|
||||
if (GameMain.GameSession.GameMode is CampaignMode campaign)
|
||||
{
|
||||
MissionPrefab prefab = null;
|
||||
Mission unlockedMission = null;
|
||||
var unlockLocation = FindUnlockLocation();
|
||||
if (unlockLocation == null && CreateLocationIfNotFound)
|
||||
{
|
||||
@@ -72,27 +72,34 @@ namespace Barotrauma
|
||||
{
|
||||
if (!MissionIdentifier.IsEmpty)
|
||||
{
|
||||
prefab = unlockLocation.UnlockMissionByIdentifier(MissionIdentifier);
|
||||
unlockedMission = unlockLocation.UnlockMissionByIdentifier(MissionIdentifier);
|
||||
}
|
||||
else if (!MissionTag.IsEmpty)
|
||||
{
|
||||
prefab = unlockLocation.UnlockMissionByTag(MissionTag);
|
||||
unlockedMission = unlockLocation.UnlockMissionByTag(MissionTag);
|
||||
}
|
||||
if (campaign is MultiPlayerCampaign mpCampaign)
|
||||
{
|
||||
mpCampaign.IncrementLastUpdateIdForFlag(MultiPlayerCampaign.NetFlags.MapAndMissions);
|
||||
}
|
||||
if (prefab != null)
|
||||
if (unlockedMission != null)
|
||||
{
|
||||
DebugConsole.NewMessage($"Unlocked mission \"{prefab.Name}\" in the location \"{unlockLocation.Name}\".");
|
||||
#if CLIENT
|
||||
new GUIMessageBox(string.Empty, TextManager.GetWithVariable("missionunlocked", "[missionname]", prefab.Name),
|
||||
Array.Empty<LocalizedString>(), type: GUIMessageBox.Type.InGame, icon: prefab.Icon, relativeSize: new Vector2(0.3f, 0.15f), minSize: new Point(512, 128))
|
||||
if (unlockedMission.Locations[0] == unlockedMission.Locations[1] || unlockedMission.Locations[1] ==null)
|
||||
{
|
||||
IconColor = prefab.IconColor
|
||||
DebugConsole.NewMessage($"Unlocked mission \"{unlockedMission.Name}\" in the location \"{unlockLocation.Name}\".");
|
||||
}
|
||||
else
|
||||
{
|
||||
DebugConsole.NewMessage($"Unlocked mission \"{unlockedMission.Name}\" in the connection from \"{unlockedMission.Locations[0].Name}\" to \"{unlockedMission.Locations[1].Name}\".");
|
||||
}
|
||||
#if CLIENT
|
||||
new GUIMessageBox(string.Empty, TextManager.GetWithVariable("missionunlocked", "[missionname]", unlockedMission.Name),
|
||||
Array.Empty<LocalizedString>(), type: GUIMessageBox.Type.InGame, icon: unlockedMission.Prefab.Icon, relativeSize: new Vector2(0.3f, 0.15f), minSize: new Point(512, 128))
|
||||
{
|
||||
IconColor = unlockedMission.Prefab.IconColor
|
||||
};
|
||||
#else
|
||||
NotifyMissionUnlock(prefab);
|
||||
#else
|
||||
NotifyMissionUnlock(unlockedMission);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -140,14 +147,15 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
#if SERVER
|
||||
private void NotifyMissionUnlock(MissionPrefab prefab)
|
||||
private void NotifyMissionUnlock(Mission mission)
|
||||
{
|
||||
foreach (Client client in GameMain.Server.ConnectedClients)
|
||||
{
|
||||
IWriteMessage outmsg = new WriteOnlyMessage();
|
||||
outmsg.WriteByte((byte)ServerPacketHeader.EVENTACTION);
|
||||
outmsg.WriteByte((byte)EventManager.NetworkEventType.MISSION);
|
||||
outmsg.WriteIdentifier(prefab.Identifier);
|
||||
outmsg.WriteIdentifier(mission.Prefab.Identifier);
|
||||
outmsg.WriteString(mission.Name.Value);
|
||||
GameMain.Server.ServerPeer.Send(outmsg, client.Connection, DeliveryMethod.Reliable);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,9 @@ namespace Barotrauma
|
||||
[Serialize(false, IsPropertySaveable.Yes)]
|
||||
public bool AddToCrew { get; set; }
|
||||
|
||||
[Serialize(false, IsPropertySaveable.Yes)]
|
||||
public bool RemoveFromCrew { get; set; }
|
||||
|
||||
private bool isFinished = false;
|
||||
|
||||
public NPCChangeTeamAction(ScriptedEvent parentEvent, ContentXElement element) : base(parentEvent, element) { }
|
||||
@@ -35,34 +38,47 @@ namespace Barotrauma
|
||||
if (AddToCrew && (TeamTag == CharacterTeamType.Team1 || TeamTag == CharacterTeamType.Team2))
|
||||
{
|
||||
npc.Info.StartItemsGiven = true;
|
||||
|
||||
GameMain.GameSession.CrewManager.AddCharacter(npc);
|
||||
ChangeItemTeam(Submarine.MainSub, true);
|
||||
if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsServer)
|
||||
{
|
||||
GameMain.NetworkMember.CreateEntityEvent(npc, new Character.AddToCrewEventData(TeamTag, npc.Inventory.AllItems));
|
||||
}
|
||||
}
|
||||
else if (RemoveFromCrew && (npc.TeamID == CharacterTeamType.Team1 || npc.TeamID == CharacterTeamType.Team2))
|
||||
{
|
||||
npc.Info.StartItemsGiven = true;
|
||||
GameMain.GameSession.CrewManager.RemoveCharacter(npc, removeInfo: true);
|
||||
var sub = Submarine.Loaded.FirstOrDefault(s => s.TeamID == TeamTag);
|
||||
ChangeItemTeam(sub, false);
|
||||
if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsServer)
|
||||
{
|
||||
GameMain.NetworkMember.CreateEntityEvent(npc, new Character.RemoveFromCrewEventData(TeamTag, npc.Inventory.AllItems));
|
||||
}
|
||||
}
|
||||
|
||||
void ChangeItemTeam(Submarine sub, bool allowStealing)
|
||||
{
|
||||
foreach (Item item in npc.Inventory.AllItems)
|
||||
{
|
||||
item.AllowStealing = true;
|
||||
var wifiComponent = item.GetComponent<Items.Components.WifiComponent>();
|
||||
if (wifiComponent != null)
|
||||
item.AllowStealing = allowStealing;
|
||||
if (item.GetComponent<Items.Components.WifiComponent>() is { } wifiComponent)
|
||||
{
|
||||
wifiComponent.TeamID = TeamTag;
|
||||
}
|
||||
var idCard = item.GetComponent<Items.Components.IdCard>();
|
||||
if (idCard != null)
|
||||
if (item.GetComponent<Items.Components.IdCard>() is { } idCard)
|
||||
{
|
||||
idCard.TeamID = TeamTag;
|
||||
idCard.SubmarineSpecificID = 0;
|
||||
}
|
||||
}
|
||||
|
||||
WayPoint subWaypoint =
|
||||
WayPoint.WayPointList.Find(wp => wp.Submarine == Submarine.MainSub && wp.SpawnType == SpawnType.Human && wp.AssignedJob == npc.Info.Job?.Prefab) ??
|
||||
WayPoint.WayPointList.Find(wp => wp.Submarine == Submarine.MainSub && wp.SpawnType == SpawnType.Human);
|
||||
WayPoint.WayPointList.Find(wp => wp.Submarine == sub && wp.SpawnType == SpawnType.Human && wp.AssignedJob == npc.Info.Job?.Prefab) ??
|
||||
WayPoint.WayPointList.Find(wp => wp.Submarine == sub && wp.SpawnType == SpawnType.Human);
|
||||
if (subWaypoint != null)
|
||||
{
|
||||
npc.GiveIdCardTags(subWaypoint, createNetworkEvent: true);
|
||||
}
|
||||
#if SERVER
|
||||
GameMain.NetworkMember.CreateEntityEvent(npc, new Character.AddToCrewEventData(TeamTag, npc.Inventory.AllItems));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
isFinished = true;
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
using Barotrauma.Extensions;
|
||||
using Microsoft.Xna.Framework;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
@@ -17,6 +14,12 @@ namespace Barotrauma
|
||||
[Serialize(true, IsPropertySaveable.Yes)]
|
||||
public bool Follow { get; set; }
|
||||
|
||||
[Serialize(-1, IsPropertySaveable.Yes)]
|
||||
public int MaxTargets { get; set; }
|
||||
|
||||
[Serialize(true, IsPropertySaveable.Yes)]
|
||||
public bool AbandonOnReset { get; set; }
|
||||
|
||||
private bool isFinished = false;
|
||||
|
||||
public NPCFollowAction(ScriptedEvent parentEvent, ContentXElement element) : base(parentEvent, element) { }
|
||||
@@ -32,6 +35,7 @@ namespace Barotrauma
|
||||
target = ParentEvent.GetTargets(TargetTag).FirstOrDefault();
|
||||
if (target == null) { return; }
|
||||
|
||||
int targetCount = 0;
|
||||
affectedNpcs = ParentEvent.GetTargets(NPCTag).Where(c => c is Character).Select(c => c as Character).ToList();
|
||||
foreach (var npc in affectedNpcs)
|
||||
{
|
||||
@@ -56,6 +60,11 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
}
|
||||
targetCount++;
|
||||
if (MaxTargets > -1 && targetCount >= MaxTargets)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
isFinished = true;
|
||||
}
|
||||
@@ -67,11 +76,11 @@ namespace Barotrauma
|
||||
|
||||
public override void Reset()
|
||||
{
|
||||
if (affectedNpcs != null && target != null)
|
||||
if (affectedNpcs != null && target != null && AbandonOnReset)
|
||||
{
|
||||
foreach (var npc in affectedNpcs)
|
||||
{
|
||||
if (npc.Removed || !(npc.AIController is HumanAIController humanAiController)) { continue; }
|
||||
if (npc.Removed || npc.AIController is not HumanAIController humanAiController) { continue; }
|
||||
foreach (var goToObjective in humanAiController.ObjectiveManager.GetActiveObjectives<AIObjectiveGoTo>())
|
||||
{
|
||||
if (goToObjective.Target == target)
|
||||
|
||||
@@ -0,0 +1,122 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
class NPCOperateItemAction : EventAction
|
||||
{
|
||||
[Serialize("", IsPropertySaveable.Yes)]
|
||||
public Identifier NPCTag { get; set; }
|
||||
|
||||
[Serialize("", IsPropertySaveable.Yes)]
|
||||
public Identifier TargetTag { get; set; }
|
||||
|
||||
[Serialize("", IsPropertySaveable.Yes)]
|
||||
public Identifier ItemComponentName { get; set; }
|
||||
|
||||
[Serialize("", IsPropertySaveable.Yes)]
|
||||
public Identifier OrderOption { get; set; }
|
||||
|
||||
[Serialize(false, IsPropertySaveable.Yes)]
|
||||
public bool RequireEquip { get; set; }
|
||||
|
||||
[Serialize(true, IsPropertySaveable.Yes)]
|
||||
public bool Operate { get; set; }
|
||||
|
||||
[Serialize(-1, IsPropertySaveable.Yes)]
|
||||
public int MaxTargets { get; set; }
|
||||
|
||||
[Serialize(true, IsPropertySaveable.Yes)]
|
||||
public bool AbandonOnReset { get; set; }
|
||||
|
||||
private bool isFinished = false;
|
||||
|
||||
public NPCOperateItemAction(ScriptedEvent parentEvent, ContentXElement element) : base(parentEvent, element) { }
|
||||
|
||||
|
||||
private List<Character> affectedNpcs = null;
|
||||
private Item target = null;
|
||||
|
||||
public override void Update(float deltaTime)
|
||||
{
|
||||
if (isFinished) { return; }
|
||||
|
||||
target = ParentEvent.GetTargets(TargetTag).FirstOrDefault() as Item;
|
||||
if (target == null) { return; }
|
||||
|
||||
int targetCount = 0;
|
||||
affectedNpcs = ParentEvent.GetTargets(NPCTag).Where(c => c is Character).Select(c => c as Character).ToList();
|
||||
foreach (var npc in affectedNpcs)
|
||||
{
|
||||
if (npc.AIController is not HumanAIController humanAiController) { continue; }
|
||||
|
||||
if (Operate)
|
||||
{
|
||||
ItemComponentName = "Controller".ToIdentifier();
|
||||
var itemComponent = target.Components.FirstOrDefault(ic => ItemComponentName == ic.Name);
|
||||
if (itemComponent == null)
|
||||
{
|
||||
DebugConsole.AddWarning($"Error in NPCOperateItemAction: could not find the component \"{ItemComponentName}\" in item \"{target.Name}\".");
|
||||
}
|
||||
else
|
||||
{
|
||||
var newObjective = new AIObjectiveOperateItem(itemComponent, npc, humanAiController.ObjectiveManager, OrderOption, RequireEquip)
|
||||
{
|
||||
OverridePriority = 100.0f
|
||||
};
|
||||
humanAiController.ObjectiveManager.AddObjective(newObjective);
|
||||
humanAiController.ObjectiveManager.WaitTimer = 0.0f;
|
||||
humanAiController.ObjectiveManager.Objectives.RemoveAll(o => o is AIObjectiveGoTo gotoOjective);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var objective in humanAiController.ObjectiveManager.Objectives)
|
||||
{
|
||||
if (objective is AIObjectiveOperateItem operateItemObjective && operateItemObjective.OperateTarget == target)
|
||||
{
|
||||
objective.Abandon = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
targetCount++;
|
||||
if (MaxTargets > -1 && targetCount >= MaxTargets)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
isFinished = true;
|
||||
}
|
||||
|
||||
public override bool IsFinished(ref string goTo)
|
||||
{
|
||||
return isFinished;
|
||||
}
|
||||
|
||||
public override void Reset()
|
||||
{
|
||||
if (affectedNpcs != null && target != null && AbandonOnReset)
|
||||
{
|
||||
foreach (var npc in affectedNpcs)
|
||||
{
|
||||
if (npc.Removed || npc.AIController is not HumanAIController humanAiController) { continue; }
|
||||
foreach (var operateItemObjective in humanAiController.ObjectiveManager.GetActiveObjectives<AIObjectiveOperateItem>())
|
||||
{
|
||||
if (operateItemObjective.OperateTarget == target)
|
||||
{
|
||||
operateItemObjective.Abandon = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
target = null;
|
||||
affectedNpcs = null;
|
||||
}
|
||||
isFinished = false;
|
||||
}
|
||||
|
||||
public override string ToDebugString()
|
||||
{
|
||||
return $"{ToolBox.GetDebugSymbol(isFinished)} {nameof(AIObjectiveOperateItem)} -> (NPCTag: {NPCTag.ColorizeObject()}, TargetTag: {TargetTag.ColorizeObject()}, Operate: {Operate.ColorizeObject()})";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -29,7 +29,7 @@ namespace Barotrauma
|
||||
|
||||
foreach (var npc in affectedNpcs)
|
||||
{
|
||||
if (!(npc.AIController is HumanAIController humanAiController)) { continue; }
|
||||
if (npc.AIController is not HumanAIController humanAiController) { continue; }
|
||||
|
||||
if (Wait)
|
||||
{
|
||||
@@ -62,7 +62,7 @@ namespace Barotrauma
|
||||
{
|
||||
foreach (var npc in affectedNpcs)
|
||||
{
|
||||
if (npc.Removed || !(npc.AIController is HumanAIController)) { continue; }
|
||||
if (npc.Removed || npc.AIController is not HumanAIController) { continue; }
|
||||
if (gotoObjective != null)
|
||||
{
|
||||
gotoObjective.Abandon = true;
|
||||
|
||||
@@ -60,6 +60,9 @@ namespace Barotrauma
|
||||
[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(100.0f, IsPropertySaveable.Yes)]
|
||||
public float Offset { get; set; }
|
||||
|
||||
[Serialize("", IsPropertySaveable.Yes, "What outpost module tags does the entity prefer to spawn in.")]
|
||||
public string TargetModuleTags
|
||||
{
|
||||
@@ -127,7 +130,7 @@ namespace Barotrauma
|
||||
ISpatialEntity spawnPos = GetSpawnPos();
|
||||
if (spawnPos != null)
|
||||
{
|
||||
Entity.Spawner.AddCharacterToSpawnQueue(CharacterPrefab.HumanSpeciesName, OffsetSpawnPos(spawnPos.WorldPosition, 100.0f), humanPrefab.CreateCharacterInfo(), onSpawn: newCharacter =>
|
||||
Entity.Spawner.AddCharacterToSpawnQueue(CharacterPrefab.HumanSpeciesName, OffsetSpawnPos(spawnPos.WorldPosition, Offset), humanPrefab.CreateCharacterInfo(), onSpawn: newCharacter =>
|
||||
{
|
||||
if (newCharacter == null) { return; }
|
||||
newCharacter.HumanPrefab = humanPrefab;
|
||||
@@ -162,7 +165,7 @@ namespace Barotrauma
|
||||
ISpatialEntity spawnPos = GetSpawnPos();
|
||||
if (spawnPos != null)
|
||||
{
|
||||
Entity.Spawner.AddCharacterToSpawnQueue(SpeciesName, OffsetSpawnPos(spawnPos.WorldPosition, 100.0f), onSpawn: newCharacter =>
|
||||
Entity.Spawner.AddCharacterToSpawnQueue(SpeciesName, OffsetSpawnPos(spawnPos.WorldPosition, Offset), onSpawn: newCharacter =>
|
||||
{
|
||||
if (!TargetTag.IsEmpty && newCharacter != null)
|
||||
{
|
||||
@@ -208,7 +211,7 @@ namespace Barotrauma
|
||||
ISpatialEntity spawnPos = GetSpawnPos();
|
||||
if (spawnPos != null)
|
||||
{
|
||||
Entity.Spawner.AddItemToSpawnQueue(itemPrefab, OffsetSpawnPos(spawnPos.WorldPosition, 100.0f), onSpawned: onSpawned);
|
||||
Entity.Spawner.AddItemToSpawnQueue(itemPrefab, OffsetSpawnPos(spawnPos.WorldPosition, Offset), onSpawned: onSpawned);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
@@ -13,7 +13,7 @@ class TutorialIconAction : EventAction
|
||||
public Identifier TargetTag { get; set; }
|
||||
|
||||
[Serialize("", IsPropertySaveable.Yes)]
|
||||
public string IconStyle { get; set; }
|
||||
public Identifier IconStyle { get; set; }
|
||||
|
||||
private bool isFinished;
|
||||
|
||||
@@ -33,7 +33,7 @@ class TutorialIconAction : EventAction
|
||||
}
|
||||
else if(Type == ActionType.Remove)
|
||||
{
|
||||
tutorialMode.Tutorial?.Icons.RemoveAll(i => i.entity == target && i.iconStyle.Equals(IconStyle, System.StringComparison.OrdinalIgnoreCase));
|
||||
tutorialMode.Tutorial?.Icons.RemoveAll(i => i.entity == target && i.iconStyle == IconStyle);
|
||||
}
|
||||
else if (Type == ActionType.RemoveTarget)
|
||||
{
|
||||
@@ -41,7 +41,7 @@ class TutorialIconAction : EventAction
|
||||
}
|
||||
else if (Type == ActionType.RemoveIcon)
|
||||
{
|
||||
tutorialMode.Tutorial?.Icons.RemoveAll(i => i.iconStyle.Equals(IconStyle, System.StringComparison.OrdinalIgnoreCase));
|
||||
tutorialMode.Tutorial?.Icons.RemoveAll(i => i.iconStyle == IconStyle);
|
||||
}
|
||||
else if (Type == ActionType.Clear)
|
||||
{
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace Barotrauma
|
||||
public SegmentActionType Type { get; set; }
|
||||
|
||||
[Serialize("", IsPropertySaveable.Yes)]
|
||||
public Identifier Id { get; set; }
|
||||
public Identifier Identifier { get; set; }
|
||||
|
||||
[Serialize("", IsPropertySaveable.Yes)]
|
||||
public Identifier ObjectiveTag { get; set; }
|
||||
@@ -30,7 +30,13 @@ namespace Barotrauma
|
||||
|
||||
private bool isFinished;
|
||||
|
||||
public TutorialSegmentAction(ScriptedEvent parentEvent, ContentXElement element) : base(parentEvent, element) { }
|
||||
public TutorialSegmentAction(ScriptedEvent parentEvent, ContentXElement element) : base(parentEvent, element)
|
||||
{
|
||||
if (Identifier.IsEmpty)
|
||||
{
|
||||
Identifier = element.GetAttributeIdentifier("id", Identifier.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
public override void Update(float deltaTime)
|
||||
{
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user