OBT/1.2.0(Spring Update)
Sync with Upstream
This commit is contained in:
@@ -233,7 +233,7 @@ namespace Barotrauma
|
||||
|
||||
}
|
||||
|
||||
protected override bool DetermineCompleted()
|
||||
protected override bool DetermineCompleted(CampaignMode.TransitionType transitionType)
|
||||
{
|
||||
return State > 0 && State != HostagesKilledState;
|
||||
}
|
||||
|
||||
@@ -171,7 +171,7 @@ namespace Barotrauma
|
||||
#endif
|
||||
}
|
||||
|
||||
protected override bool DetermineCompleted()
|
||||
protected override bool DetermineCompleted(CampaignMode.TransitionType transitionType)
|
||||
{
|
||||
return level.CheckBeaconActive();
|
||||
}
|
||||
|
||||
@@ -331,7 +331,7 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
protected override bool DetermineCompleted()
|
||||
protected override bool DetermineCompleted(CampaignMode.TransitionType transitionType)
|
||||
{
|
||||
if (Submarine.MainSub != null && Submarine.MainSub.AtEndExit)
|
||||
{
|
||||
|
||||
@@ -204,7 +204,7 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
protected override bool DetermineCompleted()
|
||||
protected override bool DetermineCompleted(CampaignMode.TransitionType transitionType)
|
||||
{
|
||||
return Winner != CharacterTeamType.None;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
#nullable enable
|
||||
namespace Barotrauma;
|
||||
|
||||
/// <summary>
|
||||
/// Defines a mission where the success and failure are determined solely by its state.
|
||||
/// Intended to be used alongside <see cref="MissionStateAction"/>.
|
||||
/// </summary>
|
||||
internal sealed partial class CustomMission(MissionPrefab prefab, Location[] locations, Submarine sub) : Mission(prefab, locations, sub)
|
||||
{
|
||||
public readonly int SuccessState = prefab.ConfigElement.GetAttributeInt(nameof(SuccessState), +1);
|
||||
public readonly int FailureState = prefab.ConfigElement.GetAttributeInt(nameof(FailureState), -1);
|
||||
|
||||
public bool RequireDestinationReached = prefab.ConfigElement.GetAttributeBool(nameof(RequireDestinationReached), false);
|
||||
|
||||
protected override bool DetermineCompleted(CampaignMode.TransitionType transitionType) =>
|
||||
State == SuccessState &&
|
||||
(!RequireDestinationReached || transitionType is CampaignMode.TransitionType.ProgressToNextLocation or CampaignMode.TransitionType.ProgressToNextEmptyLocation);
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using Barotrauma.Extensions;
|
||||
using Barotrauma.RuinGeneration;
|
||||
using Microsoft.Xna.Framework;
|
||||
@@ -199,7 +199,7 @@ namespace Barotrauma
|
||||
|
||||
private static bool IsEnemyDefeated(Character enemy) => enemy == null ||enemy.Removed || enemy.IsDead;
|
||||
|
||||
protected override bool DetermineCompleted()
|
||||
protected override bool DetermineCompleted(CampaignMode.TransitionType transitionType)
|
||||
{
|
||||
bool exitingLevel = GameMain.GameSession?.GameMode is CampaignMode campaign ?
|
||||
campaign.GetAvailableTransition() != CampaignMode.TransitionType.None :
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using Barotrauma.Extensions;
|
||||
using Barotrauma.Extensions;
|
||||
using Barotrauma.Items.Components;
|
||||
using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
@@ -301,7 +301,7 @@ namespace Barotrauma
|
||||
|
||||
partial void OnStateChangedProjSpecific();
|
||||
|
||||
protected override bool DetermineCompleted()
|
||||
protected override bool DetermineCompleted(CampaignMode.TransitionType transitionType)
|
||||
{
|
||||
return Phase == MissionPhase.BossKilled;
|
||||
}
|
||||
|
||||
@@ -343,7 +343,7 @@ namespace Barotrauma
|
||||
return character != null && !character.Removed && !character.IsDead;
|
||||
}
|
||||
|
||||
protected override bool DetermineCompleted()
|
||||
protected override bool DetermineCompleted(CampaignMode.TransitionType transitionType)
|
||||
{
|
||||
if (Submarine.MainSub != null && Submarine.MainSub.AtEndExit)
|
||||
{
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
protected override bool DetermineCompleted()
|
||||
protected override bool DetermineCompleted(CampaignMode.TransitionType transitionType)
|
||||
{
|
||||
if (Level.Loaded?.Type == LevelData.LevelType.Outpost)
|
||||
{
|
||||
@@ -25,7 +25,7 @@ namespace Barotrauma
|
||||
}
|
||||
else
|
||||
{
|
||||
return Submarine.MainSub is { AtEndExit: true };
|
||||
return transitionType == CampaignMode.TransitionType.ProgressToNextLocation;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using Barotrauma.Extensions;
|
||||
using Barotrauma.Extensions;
|
||||
using Barotrauma.Items.Components;
|
||||
using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
@@ -47,6 +47,12 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Minerals spawned by the mission. Note that minerals that were already present in the level may have also been used as targets.
|
||||
/// Each list of items represents a separate cluster of minerals.
|
||||
/// </summary>
|
||||
public IEnumerable<List<Item>> SpawnedResources => spawnedResources.Values;
|
||||
|
||||
public override LocalizedString SuccessMessage => ModifyMessage(base.SuccessMessage);
|
||||
public override LocalizedString FailureMessage => ModifyMessage(base.FailureMessage);
|
||||
public override LocalizedString Description => ModifyMessage(description);
|
||||
@@ -169,7 +175,7 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
protected override bool DetermineCompleted()
|
||||
protected override bool DetermineCompleted(CampaignMode.TransitionType transitionType)
|
||||
{
|
||||
return EnoughHaveBeenCollected();
|
||||
}
|
||||
|
||||
@@ -401,14 +401,9 @@ namespace Barotrauma
|
||||
{
|
||||
characterItems.Add(spawnedCharacter, spawnedCharacter.Inventory.FindAllItems(recursive: true));
|
||||
}
|
||||
if (submarine != null && spawnedCharacter.AIController is EnemyAIController enemyAi)
|
||||
if (spawnedCharacter.AIController is EnemyAIController enemyAi && submarine != null)
|
||||
{
|
||||
enemyAi.UnattackableSubmarines.Add(submarine);
|
||||
enemyAi.UnattackableSubmarines.Add(Submarine.MainSub);
|
||||
foreach (Submarine sub in Submarine.MainSub.DockedTo)
|
||||
{
|
||||
enemyAi.UnattackableSubmarines.Add(sub);
|
||||
}
|
||||
enemyAi.SetUnattackableSubmarines(submarine);
|
||||
}
|
||||
InitCharacter(spawnedCharacter, element);
|
||||
return spawnedCharacter;
|
||||
@@ -532,6 +527,7 @@ namespace Barotrauma
|
||||
if (GameMain.GameSession?.EventManager != null)
|
||||
{
|
||||
var newEvent = eventPrefab.CreateInstance(GameMain.GameSession.EventManager.RandomSeed);
|
||||
newEvent.TriggeringMission = this;
|
||||
GameMain.GameSession.EventManager.ActivateEvent(newEvent);
|
||||
}
|
||||
}
|
||||
@@ -539,13 +535,13 @@ namespace Barotrauma
|
||||
/// <summary>
|
||||
/// End the mission and give a reward if it was completed successfully
|
||||
/// </summary>
|
||||
public void End()
|
||||
public void End(CampaignMode.TransitionType transitionType)
|
||||
{
|
||||
if (GameMain.NetworkMember is not { IsClient: true })
|
||||
{
|
||||
completed =
|
||||
!ForceFailure &&
|
||||
DetermineCompleted() &&
|
||||
DetermineCompleted(transitionType) &&
|
||||
(completeCheckDataAction == null || completeCheckDataAction.GetSuccess());
|
||||
}
|
||||
if (completed)
|
||||
@@ -578,7 +574,7 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract bool DetermineCompleted();
|
||||
protected abstract bool DetermineCompleted(CampaignMode.TransitionType transitionType);
|
||||
|
||||
protected virtual void EndMissionSpecific(bool completed) { }
|
||||
|
||||
|
||||
@@ -30,7 +30,8 @@ namespace Barotrauma
|
||||
{ "GoTo".ToIdentifier(), typeof(GoToMission) },
|
||||
{ "ScanAlienRuins".ToIdentifier(), typeof(ScanMission) },
|
||||
{ "EliminateTargets".ToIdentifier(), typeof(EliminateTargetsMission) },
|
||||
{ "End".ToIdentifier(), typeof(EndMission) }
|
||||
{ "End".ToIdentifier(), typeof(EndMission) },
|
||||
{ "Custom".ToIdentifier(), typeof(CustomMission) }
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
@@ -64,6 +65,7 @@ namespace Barotrauma
|
||||
|
||||
public Type MissionClass { get; private set; }
|
||||
|
||||
public bool CampaignOnly { get; private set; }
|
||||
public bool MultiplayerOnly { get; private set; }
|
||||
public bool SingleplayerOnly { get; private set; }
|
||||
|
||||
@@ -319,8 +321,9 @@ namespace Barotrauma
|
||||
|
||||
SonarIconIdentifier = ConfigElement.GetAttributeIdentifier("sonaricon", "");
|
||||
|
||||
MultiplayerOnly = ConfigElement.GetAttributeBool("multiplayeronly", false);
|
||||
SingleplayerOnly = ConfigElement.GetAttributeBool("singleplayeronly", false);
|
||||
CampaignOnly = ConfigElement.GetAttributeBool(nameof(CampaignOnly), false);
|
||||
MultiplayerOnly = ConfigElement.GetAttributeBool(nameof(MultiplayerOnly), false);
|
||||
SingleplayerOnly = ConfigElement.GetAttributeBool(nameof(SingleplayerOnly), false);
|
||||
|
||||
AchievementIdentifier = ConfigElement.GetAttributeIdentifier("achievementidentifier", "");
|
||||
|
||||
@@ -543,7 +546,7 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns all mission types that can be selected e.g. in the server lobby, excluding any special, hidden ones like EndMission
|
||||
/// Returns all mission types that can be selected in the server lobby, excluding any special, hidden ones like EndMission
|
||||
/// (the mission at the end of the campaign)
|
||||
/// </summary>
|
||||
public static IEnumerable<Identifier> GetAllMultiplayerSelectableMissionTypes()
|
||||
@@ -552,6 +555,7 @@ namespace Barotrauma
|
||||
foreach (var missionPrefab in Prefabs)
|
||||
{
|
||||
if (missionPrefab.Commonness <= 0.0f) { continue; }
|
||||
if (missionPrefab.CampaignOnly) { continue; }
|
||||
if (missionPrefab.SingleplayerOnly) { continue; }
|
||||
if (HiddenMissionTypes.Contains(missionPrefab.Type))
|
||||
{
|
||||
|
||||
@@ -242,7 +242,7 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
protected override bool DetermineCompleted()
|
||||
protected override bool DetermineCompleted(CampaignMode.TransitionType transitionType)
|
||||
{
|
||||
return state > 0;
|
||||
}
|
||||
|
||||
@@ -337,7 +337,7 @@ namespace Barotrauma
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override bool DetermineCompleted()
|
||||
protected override bool DetermineCompleted(CampaignMode.TransitionType transitionType)
|
||||
{
|
||||
return AllItemsDestroyedOrRetrieved();
|
||||
}
|
||||
|
||||
@@ -547,7 +547,7 @@ namespace Barotrauma
|
||||
return character == null || character.Removed || character.Submarine == null || (character.LockHands && character.Submarine == Submarine.MainSub) || character.IsIncapacitated;
|
||||
}
|
||||
|
||||
protected override bool DetermineCompleted()
|
||||
protected override bool DetermineCompleted(CampaignMode.TransitionType transitionType)
|
||||
{
|
||||
return state == 2;
|
||||
}
|
||||
|
||||
@@ -715,7 +715,7 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
protected override bool DetermineCompleted()
|
||||
protected override bool DetermineCompleted(CampaignMode.TransitionType transitionType)
|
||||
{
|
||||
if (requiredDeliveryAmount < 1.0f)
|
||||
{
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using Barotrauma.Extensions;
|
||||
using Barotrauma.Items.Components;
|
||||
using Barotrauma.RuinGeneration;
|
||||
@@ -17,7 +17,7 @@ namespace Barotrauma
|
||||
private readonly Dictionary<Item, ushort> parentInventoryIDs = new Dictionary<Item, ushort>();
|
||||
private readonly Dictionary<Item, int> inventorySlotIndices = new Dictionary<Item, int>();
|
||||
private readonly Dictionary<Item, byte> parentItemContainerIndices = new Dictionary<Item, byte>();
|
||||
private readonly int targetsToScan;
|
||||
private readonly int totalTargetsToScan;
|
||||
private readonly Dictionary<WayPoint, bool> scanTargets = new Dictionary<WayPoint, bool>();
|
||||
private readonly HashSet<WayPoint> newTargetsScanned = new HashSet<WayPoint>();
|
||||
private readonly float minTargetDistance;
|
||||
@@ -44,7 +44,7 @@ namespace Barotrauma
|
||||
public ScanMission(MissionPrefab prefab, Location[] locations, Submarine sub) : base(prefab, locations, sub)
|
||||
{
|
||||
itemConfig = prefab.ConfigElement.GetChildElement("Items");
|
||||
targetsToScan = prefab.ConfigElement.GetAttributeInt("targets", 1);
|
||||
totalTargetsToScan = prefab.ConfigElement.GetAttributeInt("targets", 1);
|
||||
minTargetDistance = prefab.ConfigElement.GetAttributeFloat("mintargetdistance", 0.0f);
|
||||
}
|
||||
|
||||
@@ -77,57 +77,60 @@ namespace Barotrauma
|
||||
|
||||
var ruinWaypoints = TargetRuin.Submarine.GetWaypoints(false);
|
||||
ruinWaypoints.RemoveAll(wp => wp.CurrentHull == null);
|
||||
if (ruinWaypoints.Count < targetsToScan)
|
||||
if (ruinWaypoints.Count < totalTargetsToScan)
|
||||
{
|
||||
DebugConsole.ThrowError($"Failed to initialize a Scan mission: target ruin has less waypoints than required as scan targets ({ruinWaypoints.Count} < {targetsToScan})",
|
||||
DebugConsole.ThrowError($"Failed to initialize a Scan mission: target ruin has less waypoints than required as scan targets ({ruinWaypoints.Count} < {totalTargetsToScan})",
|
||||
contentPackage: Prefab.ContentPackage);
|
||||
return;
|
||||
}
|
||||
|
||||
//the distance we'll use if we otherwise fail to place the targets far enough from each other
|
||||
//(smallest extent should be large enough to fit the targets and one extra to be safe)
|
||||
float guaranteedDistance = Math.Min(TargetRuin.Area.Width, TargetRuin.Area.Height) / (totalTargetsToScan + 1);
|
||||
|
||||
var availableWaypoints = new List<WayPoint>();
|
||||
float minTargetDistanceSquared = minTargetDistance * minTargetDistance;
|
||||
for (int tries = 0; tries < 15; tries++)
|
||||
const int MaxTries = 15;
|
||||
for (int tries = 0; tries < MaxTries; tries++)
|
||||
{
|
||||
float triesNormalized = tries / (float)(MaxTries - 1); // 0.0 -> 1.0
|
||||
float desperationFactor = MathF.Pow(triesNormalized, 2);
|
||||
//try placing the targets the desired minimum distance apart, gradually lowering the distance requirement on each try
|
||||
float currentMinDistance = MathHelper.Lerp(minTargetDistance, guaranteedDistance, desperationFactor);
|
||||
float currentMinDistanceSquared = currentMinDistance * currentMinDistance;
|
||||
|
||||
scanTargets.Clear();
|
||||
availableWaypoints.Clear();
|
||||
availableWaypoints.AddRange(ruinWaypoints);
|
||||
for (int i = 0; i < targetsToScan; i++)
|
||||
for (int i = 0; i < totalTargetsToScan; i++)
|
||||
{
|
||||
var selectedWaypoint = availableWaypoints.GetRandom(randSync: Rand.RandSync.ServerAndClient);
|
||||
scanTargets.Add(selectedWaypoint, false);
|
||||
availableWaypoints.Remove(selectedWaypoint);
|
||||
if (i < (targetsToScan - 1))
|
||||
if (i < (totalTargetsToScan - 1))
|
||||
{
|
||||
availableWaypoints.RemoveAll(wp => wp.CurrentHull == selectedWaypoint.CurrentHull);
|
||||
availableWaypoints.RemoveAll(wp => Vector2.DistanceSquared(wp.WorldPosition, selectedWaypoint.WorldPosition) < minTargetDistanceSquared);
|
||||
availableWaypoints.RemoveAll(wp => Vector2.DistanceSquared(wp.WorldPosition, selectedWaypoint.WorldPosition) < currentMinDistanceSquared);
|
||||
if (availableWaypoints.None())
|
||||
{
|
||||
#if DEBUG
|
||||
DebugConsole.ThrowError($"Error initializing a Scan mission: not enough targets available on try #{tries + 1} to reach the required scan target count (current targets: {scanTargets.Count}, required targets: {targetsToScan})",
|
||||
DebugConsole.ThrowError($"Error initializing a Scan mission: not enough targets available on try #{tries + 1} to reach the required scan target count (current targets: {scanTargets.Count}, required targets: {totalTargetsToScan})",
|
||||
contentPackage: Prefab.ContentPackage);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (scanTargets.Count >= targetsToScan)
|
||||
if (scanTargets.Count >= totalTargetsToScan)
|
||||
{
|
||||
#if DEBUG
|
||||
DebugConsole.NewMessage($"Successfully initialized a Scan mission: targets set on try #{tries + 1}", Color.Green);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
if ((tries + 1) % 5 == 0)
|
||||
{
|
||||
float reducedMinTargetDistance = (1.0f - (((tries + 1) / 5) * 0.1f)) * minTargetDistance;
|
||||
minTargetDistanceSquared = reducedMinTargetDistance * reducedMinTargetDistance;
|
||||
#if DEBUG
|
||||
DebugConsole.NewMessage($"Reducing minimum distance between Scan mission targets (new min: {reducedMinTargetDistance}) to reach the required target count", Color.Yellow);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
if (scanTargets.Count < targetsToScan)
|
||||
if (scanTargets.Count < totalTargetsToScan)
|
||||
{
|
||||
DebugConsole.ThrowError($"Error initializing a Scan mission: not enough targets (current targets: {scanTargets.Count}, required targets: {targetsToScan})",
|
||||
DebugConsole.ThrowError($"Error initializing a Scan mission: not enough targets (current targets: {scanTargets.Count}, required targets: {totalTargetsToScan})",
|
||||
contentPackage: Prefab.ContentPackage);
|
||||
}
|
||||
}
|
||||
@@ -241,9 +244,9 @@ namespace Barotrauma
|
||||
State = Math.Max(State, scanTargets.Count(kvp => kvp.Value));
|
||||
}
|
||||
|
||||
private bool AllTargetsScanned() => State >= targetsToScan;
|
||||
private bool AllTargetsScanned() => State >= totalTargetsToScan;
|
||||
|
||||
protected override bool DetermineCompleted() => AllTargetsScanned();
|
||||
protected override bool DetermineCompleted(CampaignMode.TransitionType transitionType) => AllTargetsScanned();
|
||||
|
||||
protected override void EndMissionSpecific(bool completed)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user