v1.0.13.1 (first post-1.0 patch)
This commit is contained in:
@@ -9,6 +9,8 @@ namespace Barotrauma
|
||||
public event Action Finished;
|
||||
protected bool isFinished;
|
||||
|
||||
public int RandomSeed;
|
||||
|
||||
protected readonly EventPrefab prefab;
|
||||
|
||||
public EventPrefab Prefab => prefab;
|
||||
|
||||
@@ -31,6 +31,8 @@ namespace Barotrauma
|
||||
|
||||
private bool isFinished;
|
||||
|
||||
private readonly Random random;
|
||||
|
||||
public MissionAction(ScriptedEvent parentEvent, ContentXElement element) : base(parentEvent, element)
|
||||
{
|
||||
if (MissionIdentifier.IsEmpty && MissionTag.IsEmpty)
|
||||
@@ -42,6 +44,7 @@ namespace Barotrauma
|
||||
DebugConsole.ThrowError($"Error in event \"{parentEvent.Prefab.Identifier}\": both MissionIdentifier or MissionTag have been configured. The tag will be ignored.");
|
||||
}
|
||||
LocationTypes = element.GetAttributeIdentifierArray("locationtype", Array.Empty<Identifier>()).ToImmutableArray();
|
||||
random = new MTRandom(parentEvent.RandomSeed);
|
||||
}
|
||||
|
||||
public override bool IsFinished(ref string goTo)
|
||||
@@ -80,7 +83,7 @@ namespace Barotrauma
|
||||
}
|
||||
else if (!MissionTag.IsEmpty)
|
||||
{
|
||||
unlockedMission = unlockLocation.UnlockMissionByTag(MissionTag);
|
||||
unlockedMission = unlockLocation.UnlockMissionByTag(MissionTag, random);
|
||||
}
|
||||
if (campaign is MultiPlayerCampaign mpCampaign)
|
||||
{
|
||||
|
||||
@@ -31,7 +31,8 @@ namespace Barotrauma
|
||||
|
||||
if (Wait)
|
||||
{
|
||||
var gotoObjective = new AIObjectiveGoTo(npc, npc, humanAiController.ObjectiveManager, repeat: true)
|
||||
var gotoObjective = new AIObjectiveGoTo(
|
||||
AIObjectiveGoTo.GetTargetHull(npc) as ISpatialEntity ?? npc, npc, humanAiController.ObjectiveManager, repeat: true)
|
||||
{
|
||||
OverridePriority = 100.0f,
|
||||
SourceEventAction = this
|
||||
|
||||
@@ -188,6 +188,10 @@ namespace Barotrauma
|
||||
outPostInfo.AddOutpostNPCIdentifierOrTag(newCharacter, tag);
|
||||
}
|
||||
}
|
||||
#if SERVER
|
||||
newCharacter.LoadTalents();
|
||||
GameMain.NetworkMember.CreateEntityEvent(newCharacter, new Character.UpdateTalentsEventData());
|
||||
#endif
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Barotrauma.Extensions;
|
||||
using Barotrauma.Items.Components;
|
||||
using FarseerPhysics;
|
||||
using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
@@ -72,7 +73,7 @@ namespace Barotrauma
|
||||
|
||||
private readonly List<Event> activeEvents = new List<Event>();
|
||||
|
||||
private readonly HashSet<Identifier> finishedEvents = new HashSet<Identifier>();
|
||||
private readonly HashSet<Event> finishedEvents = new HashSet<Event>();
|
||||
private readonly HashSet<Identifier> nonRepeatableEvents = new HashSet<Identifier>();
|
||||
private readonly HashSet<EventSet> usedUniqueSets = new HashSet<EventSet>();
|
||||
|
||||
@@ -123,7 +124,8 @@ namespace Barotrauma
|
||||
|
||||
public bool Enabled = true;
|
||||
|
||||
private MTRandom rand;
|
||||
private MTRandom random;
|
||||
private int randomSeed;
|
||||
|
||||
public void StartRound(Level level)
|
||||
{
|
||||
@@ -147,23 +149,22 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
SelectSettings();
|
||||
|
||||
int seed = 0;
|
||||
|
||||
if (level != null)
|
||||
{
|
||||
seed = ToolBox.StringToInt(level.Seed);
|
||||
randomSeed = ToolBox.StringToInt(level.Seed);
|
||||
foreach (var previousEvent in level.LevelData.EventHistory)
|
||||
{
|
||||
seed ^= ToolBox.IdentifierToInt(previousEvent);
|
||||
randomSeed ^= ToolBox.IdentifierToInt(previousEvent);
|
||||
}
|
||||
}
|
||||
rand = new MTRandom(seed);
|
||||
random = new MTRandom(randomSeed);
|
||||
|
||||
bool playingCampaign = GameMain.GameSession?.GameMode is CampaignMode;
|
||||
EventSet initialEventSet = SelectRandomEvents(
|
||||
EventSet.Prefabs.ToList(),
|
||||
requireCampaignSet: playingCampaign,
|
||||
random: rand);
|
||||
random: random);
|
||||
EventSet additiveSet = null;
|
||||
if (initialEventSet != null && initialEventSet.Additive)
|
||||
{
|
||||
@@ -171,7 +172,7 @@ namespace Barotrauma
|
||||
initialEventSet = SelectRandomEvents(
|
||||
EventSet.Prefabs.Where(e => !e.Additive).ToList(),
|
||||
requireCampaignSet: playingCampaign,
|
||||
random: rand);
|
||||
random: random);
|
||||
}
|
||||
if (initialEventSet != null)
|
||||
{
|
||||
@@ -366,20 +367,49 @@ namespace Barotrauma
|
||||
/// <summary>
|
||||
/// Registers the exhaustible events in the level as exhausted, and adds the current events to the event history
|
||||
/// </summary>
|
||||
public void RegisterEventHistory()
|
||||
public void RegisterEventHistory(bool registerFinishedOnly = false)
|
||||
{
|
||||
if (level?.LevelData == null) { return; }
|
||||
|
||||
level.LevelData.EventsExhausted = !registerFinishedOnly;
|
||||
|
||||
if (level.LevelData.Type == LevelData.LevelType.Outpost)
|
||||
{
|
||||
level.LevelData.EventsExhausted = true;
|
||||
level.LevelData.EventHistory.AddRange(selectedEvents.Values.SelectMany(v => v).Select(e => e.Prefab.Identifier).Where(e => !level.LevelData.EventHistory.Contains(e)));
|
||||
if (registerFinishedOnly)
|
||||
{
|
||||
foreach (var finishedEvent in finishedEvents)
|
||||
{
|
||||
var key = finishedEvent.ParentSet;
|
||||
if (key == null) { continue; }
|
||||
if (level.LevelData.FinishedEvents.ContainsKey(key))
|
||||
{
|
||||
level.LevelData.FinishedEvents[key] += 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
level.LevelData.FinishedEvents.Add(key, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
level.LevelData.EventHistory.AddRange(selectedEvents.Values
|
||||
.SelectMany(v => v)
|
||||
.Select(e => e.Prefab.Identifier)
|
||||
.Where(eventId => Register(eventId) && !level.LevelData.EventHistory.Contains(eventId)));
|
||||
|
||||
if (level.LevelData.EventHistory.Count > MaxEventHistory)
|
||||
{
|
||||
level.LevelData.EventHistory.RemoveRange(0, level.LevelData.EventHistory.Count - MaxEventHistory);
|
||||
}
|
||||
}
|
||||
level.LevelData.NonRepeatableEvents.AddRange(nonRepeatableEvents.Where(e => !level.LevelData.NonRepeatableEvents.Contains(e)));
|
||||
level.LevelData.NonRepeatableEvents.AddRange(nonRepeatableEvents.Where(eventId => Register(eventId) && !level.LevelData.NonRepeatableEvents.Contains(eventId)));
|
||||
|
||||
if (!registerFinishedOnly)
|
||||
{
|
||||
level.LevelData.FinishedEvents.Clear();
|
||||
}
|
||||
|
||||
bool Register(Identifier eventId) => !registerFinishedOnly || finishedEvents.Any(fe => fe.Prefab.Identifier == eventId);
|
||||
}
|
||||
|
||||
public void SkipEventCooldown()
|
||||
@@ -462,14 +492,14 @@ namespace Barotrauma
|
||||
for (int j = 0; j < eventCount; j++)
|
||||
{
|
||||
if (unusedEvents.All(e => e.EventPrefabs.All(p => CalculateCommonness(p, e.Commonness) <= 0.0f))) { break; }
|
||||
EventSet.SubEventPrefab subEventPrefab = ToolBox.SelectWeightedRandom(unusedEvents, e => e.EventPrefabs.Max(p => CalculateCommonness(p, e.Commonness)), rand);
|
||||
EventSet.SubEventPrefab subEventPrefab = ToolBox.SelectWeightedRandom(unusedEvents, e => e.EventPrefabs.Max(p => CalculateCommonness(p, e.Commonness)), random);
|
||||
(IEnumerable<EventPrefab> eventPrefabs, float commonness, float probability) = subEventPrefab;
|
||||
if (eventPrefabs != null && rand.NextDouble() <= probability)
|
||||
if (eventPrefabs != null && random.NextDouble() <= probability)
|
||||
{
|
||||
var eventPrefab = ToolBox.SelectWeightedRandom(eventPrefabs.Where(isPrefabSuitable), e => e.Commonness, rand);
|
||||
|
||||
var eventPrefab = ToolBox.SelectWeightedRandom(eventPrefabs.Where(isPrefabSuitable), e => e.Commonness, random);
|
||||
var newEvent = eventPrefab.CreateInstance();
|
||||
if (newEvent == null) { continue; }
|
||||
newEvent.RandomSeed = randomSeed;
|
||||
if (i < spawnPosFilter.Count) { newEvent.SpawnPosFilter = spawnPosFilter[i]; }
|
||||
DebugConsole.NewMessage($"Initialized event {newEvent}", debugOnly: true);
|
||||
if (!selectedEvents.ContainsKey(eventSet))
|
||||
@@ -483,7 +513,7 @@ namespace Barotrauma
|
||||
}
|
||||
if (eventSet.ChildSets.Any())
|
||||
{
|
||||
var newEventSet = SelectRandomEvents(eventSet.ChildSets, random: rand);
|
||||
var newEventSet = SelectRandomEvents(eventSet.ChildSets, random: random);
|
||||
if (newEventSet != null)
|
||||
{
|
||||
CreateEvents(newEventSet);
|
||||
@@ -494,9 +524,9 @@ namespace Barotrauma
|
||||
{
|
||||
foreach ((IEnumerable<EventPrefab> eventPrefabs, float commonness, float probability) in suitablePrefabSubsets)
|
||||
{
|
||||
if (rand.NextDouble() > probability) { continue; }
|
||||
if (random.NextDouble() > probability) { continue; }
|
||||
|
||||
var eventPrefab = ToolBox.SelectWeightedRandom(eventPrefabs.Where(isPrefabSuitable), e => e.Commonness, rand);
|
||||
var eventPrefab = ToolBox.SelectWeightedRandom(eventPrefabs.Where(isPrefabSuitable), e => e.Commonness, random);
|
||||
var newEvent = eventPrefab.CreateInstance();
|
||||
if (newEvent == null) { continue; }
|
||||
if (!selectedEvents.ContainsKey(eventSet))
|
||||
@@ -783,13 +813,13 @@ namespace Barotrauma
|
||||
{
|
||||
ev.Update(deltaTime);
|
||||
}
|
||||
else if (ev.Prefab != null && !finishedEvents.Contains(ev.Prefab.Identifier))
|
||||
else if (ev.Prefab != null && !finishedEvents.Any(e => e.Prefab == ev.Prefab))
|
||||
{
|
||||
if (level?.LevelData != null && level.LevelData.Type == LevelData.LevelType.Outpost)
|
||||
{
|
||||
if (!level.LevelData.EventHistory.Contains(ev.Prefab.Identifier)) { level.LevelData.EventHistory.Add(ev.Prefab.Identifier); }
|
||||
}
|
||||
finishedEvents.Add(ev.Prefab.Identifier);
|
||||
finishedEvents.Add(ev);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -833,30 +863,44 @@ namespace Barotrauma
|
||||
monsterStrength = 0;
|
||||
foreach (Character character in Character.CharacterList)
|
||||
{
|
||||
if (character.IsIncapacitated || !character.Enabled || character.IsPet || CharacterParams.CompareGroup(CharacterPrefab.HumanSpeciesName, character.Group)) { continue; }
|
||||
if (character.IsIncapacitated || character.IsArrested || !character.Enabled || character.IsPet) { continue; }
|
||||
|
||||
if (!(character.AIController is EnemyAIController enemyAI)) { continue; }
|
||||
|
||||
if (!enemyAI.AIParams.StayInAbyss)
|
||||
if (character.AIController is EnemyAIController enemyAI)
|
||||
{
|
||||
// Ignore abyss monsters because they can stay active for quite great distances. They'll be taken into account when they target the sub.
|
||||
monsterStrength += enemyAI.CombatStrength;
|
||||
if (!enemyAI.AIParams.StayInAbyss)
|
||||
{
|
||||
// Ignore abyss monsters because they can stay active for quite great distances. They'll be taken into account when they target the sub.
|
||||
monsterStrength += enemyAI.CombatStrength;
|
||||
}
|
||||
|
||||
if (character.CurrentHull?.Submarine?.Info != null &&
|
||||
(character.CurrentHull.Submarine == Submarine.MainSub || Submarine.MainSub.DockedTo.Contains(character.CurrentHull.Submarine)) &&
|
||||
character.CurrentHull.Submarine.Info.Type == SubmarineType.Player)
|
||||
{
|
||||
// Enemy onboard -> Crawler inside the sub adds 0.2 to enemy danger, Mudraptor 0.42
|
||||
enemyDanger += enemyAI.CombatStrength / 500.0f;
|
||||
}
|
||||
else if (enemyAI.SelectedAiTarget?.Entity?.Submarine != null)
|
||||
{
|
||||
// Enemy outside targeting the sub or something in it
|
||||
// -> One Crawler adds 0.02, a Mudraptor 0.042, a Hammerhead 0.1, and a Moloch 0.25.
|
||||
enemyDanger += enemyAI.CombatStrength / 5000.0f;
|
||||
}
|
||||
}
|
||||
|
||||
if (character.CurrentHull?.Submarine?.Info != null &&
|
||||
(character.CurrentHull.Submarine == Submarine.MainSub || Submarine.MainSub.DockedTo.Contains(character.CurrentHull.Submarine)) &&
|
||||
character.CurrentHull.Submarine.Info.Type == SubmarineType.Player)
|
||||
else if (character.AIController is HumanAIController humanAi && !character.IsOnFriendlyTeam(CharacterTeamType.Team1))
|
||||
{
|
||||
// Enemy onboard -> Crawler inside the sub adds 0.2 to enemy danger, Mudraptor 0.42
|
||||
enemyDanger += enemyAI.CombatStrength / 500.0f;
|
||||
}
|
||||
else if (enemyAI.SelectedAiTarget?.Entity?.Submarine != null)
|
||||
{
|
||||
// Enemy outside targeting the sub or something in it
|
||||
// -> One Crawler adds 0.02, a Mudraptor 0.042, a Hammerhead 0.1, and a Moloch 0.25.
|
||||
enemyDanger += enemyAI.CombatStrength / 5000.0f;
|
||||
if (character.Submarine != null &&
|
||||
character.Submarine.PhysicsBody is { BodyType: BodyType.Dynamic } &&
|
||||
Vector2.DistanceSquared(character.Submarine.WorldPosition, Submarine.MainSub.WorldPosition) < Sonar.DefaultSonarRange * Sonar.DefaultSonarRange)
|
||||
{
|
||||
//we have no easy way to define the strength of a human enemy (depends more on the sub and it's state than the character),
|
||||
//so let's just go with a fixed value.
|
||||
//5 living enemy characters in an enemy sub in sonar range is enough to bump the intensity to max
|
||||
enemyDanger += 0.2f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add a portion of the total strength of active monsters to the enemy danger so that we don't spawn too many monsters around the sub.
|
||||
// On top of the existing value, so if 10 crawlers are targeting the sub simultaneously from outside, the final value would be: 0.02 x 10 + 0.2 = 0.4.
|
||||
// And if they get inside, we add 0.1 per crawler on that.
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Reflection.Emit;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
|
||||
@@ -396,8 +396,16 @@ namespace Barotrauma
|
||||
|
||||
public int GetEventCount(Level level)
|
||||
{
|
||||
if (level?.StartLocation == null || !overrideEventCount.TryGetValue(level.StartLocation.Type.Identifier, out int count)) { return eventCount; }
|
||||
return count;
|
||||
int finishedEventCount = 0;
|
||||
if (level is not null)
|
||||
{
|
||||
level.LevelData.FinishedEvents.TryGetValue(this, out finishedEventCount);
|
||||
}
|
||||
if (level.StartLocation == null || !overrideEventCount.TryGetValue(level.StartLocation.Type.Identifier, out int count))
|
||||
{
|
||||
return eventCount - finishedEventCount;
|
||||
}
|
||||
return count - finishedEventCount;
|
||||
}
|
||||
|
||||
public static List<string> GetDebugStatistics(int simulatedRoundCount = 100, Func<MonsterEvent, bool> filter = null, bool fullLog = false)
|
||||
|
||||
@@ -401,7 +401,7 @@ namespace Barotrauma
|
||||
int reward = GetReward(sub);
|
||||
IEnumerable<Character> crewCharacters = GameSession.GetSessionCrewCharacters(CharacterType.Both);
|
||||
var missionMoneyGainMultiplier = new AbilityMissionMoneyGainMultiplier(this, 1f);
|
||||
crewCharacters.ForEach(c => c.CheckTalents(AbilityEffectType.OnGainMissionMoney, missionMoneyGainMultiplier));
|
||||
CharacterTalent.CheckTalentsForCrew(crewCharacters, AbilityEffectType.OnGainMissionMoney, missionMoneyGainMultiplier);
|
||||
crewCharacters.ForEach(c => missionMoneyGainMultiplier.Value += c.GetStatValue(StatTypes.MissionMoneyGainMultiplier));
|
||||
finalReward = (int)(reward * missionMoneyGainMultiplier.Value);
|
||||
}
|
||||
|
||||
@@ -380,11 +380,11 @@ namespace Barotrauma
|
||||
{
|
||||
if (fromType == "any" ||
|
||||
fromType == from.Type.Identifier ||
|
||||
(fromType == "anyoutpost" && from.HasOutpost()))
|
||||
(fromType == "anyoutpost" && from.HasOutpost() && from.Type.Identifier != "abandoned"))
|
||||
{
|
||||
if (toType == "any" ||
|
||||
toType == to.Type.Identifier ||
|
||||
(toType == "anyoutpost" && to.HasOutpost()))
|
||||
(toType == "anyoutpost" && to.HasOutpost() && to.Type.Identifier != "abandoned"))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -260,9 +260,25 @@ namespace Barotrauma
|
||||
int amount = Rand.Range(monster.Item2.X, monster.Item2.Y + 1);
|
||||
for (int i = 0; i < amount; i++)
|
||||
{
|
||||
Character.Create(monster.Item1.Identifier, nestPosition + Rand.Vector(100.0f), ToolBox.RandomSeed(8), createNetworkEvent: true);
|
||||
Vector2 offsetPosition;
|
||||
int tries = 0;
|
||||
do
|
||||
{
|
||||
offsetPosition = nestPosition + Rand.Vector(100.0f);
|
||||
tries++;
|
||||
if (tries > 10)
|
||||
{
|
||||
offsetPosition = nestPosition;
|
||||
break;
|
||||
}
|
||||
} while (Level.Loaded.IsPositionInsideWall(offsetPosition));
|
||||
Character.Create(monster.Item1.Identifier, offsetPosition, ToolBox.RandomSeed(8), createNetworkEvent: true);
|
||||
}
|
||||
}
|
||||
if (Level.Loaded.IsPositionInsideWall(nestPosition))
|
||||
{
|
||||
DebugConsole.AddWarning($"Error in nest mission \"{Prefab.Identifier}\": nest position was inside a wall ({nestPosition}).");
|
||||
}
|
||||
monsterPrefabs.Clear();
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -19,6 +19,8 @@ namespace Barotrauma
|
||||
private float missionDifficulty;
|
||||
private int alternateReward;
|
||||
|
||||
private Identifier factionIdentifier;
|
||||
|
||||
private Submarine enemySub;
|
||||
private readonly List<Character> characters = new List<Character>();
|
||||
private readonly Dictionary<Character, List<Item>> characterItems = new Dictionary<Character, List<Item>>();
|
||||
@@ -140,8 +142,8 @@ namespace Barotrauma
|
||||
missionDifficulty = level?.Difficulty ?? 0;
|
||||
|
||||
XElement submarineConfig = GetRandomDifficultyModifiedElement(submarineTypeConfig, missionDifficulty, ShipRandomnessModifier);
|
||||
|
||||
alternateReward = submarineConfig.GetAttributeInt("alternatereward", Reward);
|
||||
factionIdentifier = submarineConfig.GetAttributeIdentifier("faction", Identifier.Empty);
|
||||
|
||||
string rewardText = $"‖color:gui.orange‖{string.Format(System.Globalization.CultureInfo.InvariantCulture, "{0:N0}", alternateReward)}‖end‖";
|
||||
if (descriptionWithoutReward != null) { description = descriptionWithoutReward.Replace("[reward]", rewardText); }
|
||||
@@ -170,11 +172,11 @@ namespace Barotrauma
|
||||
submarineInfo = new SubmarineInfo(contentFile.Path.Value);
|
||||
}
|
||||
|
||||
private float GetDifficultyModifiedValue(float preferredDifficulty, float levelDifficulty, float randomnessModifier, Random rand)
|
||||
private static float GetDifficultyModifiedValue(float preferredDifficulty, float levelDifficulty, float randomnessModifier, Random rand)
|
||||
{
|
||||
return Math.Abs(levelDifficulty - preferredDifficulty + MathHelper.Lerp(-randomnessModifier, randomnessModifier, (float)rand.NextDouble()));
|
||||
}
|
||||
private int GetDifficultyModifiedAmount(int minAmount, int maxAmount, float levelDifficulty, Random rand)
|
||||
private static int GetDifficultyModifiedAmount(int minAmount, int maxAmount, float levelDifficulty, Random rand)
|
||||
{
|
||||
return Math.Max((int)Math.Round(minAmount + (maxAmount - minAmount) * (levelDifficulty + MathHelper.Lerp(-RandomnessModifier, RandomnessModifier, (float)rand.NextDouble())) / MaxDifficulty), minAmount);
|
||||
}
|
||||
@@ -254,6 +256,7 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
enemySub.ImmuneToBallastFlora = true;
|
||||
enemySub.EnableFactionSpecificEntities(factionIdentifier);
|
||||
}
|
||||
|
||||
private void InitPirates()
|
||||
@@ -444,7 +447,7 @@ namespace Barotrauma
|
||||
|
||||
private bool CheckWinState() => !IsClient && characters.All(m => DeadOrCaptured(m));
|
||||
|
||||
private bool DeadOrCaptured(Character character)
|
||||
private static bool DeadOrCaptured(Character character)
|
||||
{
|
||||
return character == null || character.Removed || character.Submarine == null || (character.LockHands && character.Submarine == Submarine.MainSub) || character.IsIncapacitated;
|
||||
}
|
||||
|
||||
@@ -16,8 +16,8 @@ namespace Barotrauma
|
||||
public Item Item;
|
||||
|
||||
/// <summary>
|
||||
/// Note that the integer values matter here: the state of the target can't go back to a smaller value,
|
||||
/// and a larger or equal value than the <see href="RequiredRetrievalState">RequiredRetrievalState</see> means the item counts as retrieved
|
||||
/// Note that the integer values matter here:
|
||||
/// a larger or equal value than the <see href="RequiredRetrievalState">RequiredRetrievalState</see> means the item counts as retrieved
|
||||
/// (if the item needs to be picked up to be considered retrieved, it's also considered retrieved if it's in the sub)
|
||||
/// </summary>
|
||||
public enum RetrievalState
|
||||
@@ -167,6 +167,8 @@ namespace Barotrauma
|
||||
|
||||
private readonly List<Target> targets = new List<Target>();
|
||||
|
||||
public bool AnyTargetNeedsToBeRetrievedToSub => targets.Any(t => t.RequiredRetrievalState == Target.RetrievalState.RetrievedToSub && !t.Retrieved);
|
||||
|
||||
public override IEnumerable<(LocalizedString Label, Vector2 Position)> SonarLabels
|
||||
{
|
||||
get
|
||||
@@ -382,29 +384,55 @@ namespace Barotrauma
|
||||
switch (target.State)
|
||||
{
|
||||
case Target.RetrievalState.None:
|
||||
if (target.Interacted)
|
||||
{
|
||||
TrySetRetrievalState(Target.RetrievalState.Interact);
|
||||
}
|
||||
var root = target.Item?.GetRootContainer() ?? target.Item;
|
||||
if (root.ParentInventory?.Owner is Character character && character.TeamID == CharacterTeamType.Team1)
|
||||
{
|
||||
TrySetRetrievalState(Target.RetrievalState.PickedUp);
|
||||
if (target.Interacted)
|
||||
{
|
||||
TrySetRetrievalState(Target.RetrievalState.Interact);
|
||||
}
|
||||
var root = target.Item?.GetRootContainer() ?? target.Item;
|
||||
if (root.ParentInventory?.Owner is Character character && character.TeamID == CharacterTeamType.Team1)
|
||||
{
|
||||
TrySetRetrievalState(Target.RetrievalState.PickedUp);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case Target.RetrievalState.PickedUp:
|
||||
Submarine parentSub = target.Item.CurrentHull?.Submarine ?? target.Item.GetRootInventoryOwner()?.Submarine;
|
||||
if (parentSub != null && parentSub.Info.Type == SubmarineType.Player)
|
||||
case Target.RetrievalState.RetrievedToSub:
|
||||
{
|
||||
TrySetRetrievalState(Target.RetrievalState.RetrievedToSub);
|
||||
Entity rootInventoryOwner = target.Item.GetRootInventoryOwner();
|
||||
Submarine parentSub = target.Item.CurrentHull?.Submarine ?? rootInventoryOwner?.Submarine;
|
||||
|
||||
bool inPlayerSub = parentSub != null && parentSub.Info.Type == SubmarineType.Player;
|
||||
bool inPlayerInventory = false;
|
||||
bool playerInFriendlySub = false;
|
||||
if (rootInventoryOwner is Character character && character.TeamID == CharacterTeamType.Team1)
|
||||
{
|
||||
inPlayerInventory = true;
|
||||
if (character.Submarine != null)
|
||||
{
|
||||
playerInFriendlySub =
|
||||
character.IsInFriendlySub ||
|
||||
(character.Submarine == Level.Loaded?.StartOutpost && Level.IsLoadedFriendlyOutpost && GameMain.GameSession?.Campaign.CurrentLocation is not { IsFactionHostile: true });
|
||||
}
|
||||
}
|
||||
|
||||
if (inPlayerSub || (inPlayerInventory && playerInFriendlySub))
|
||||
{
|
||||
TrySetRetrievalState(Target.RetrievalState.RetrievedToSub);
|
||||
}
|
||||
else
|
||||
{
|
||||
target.State = Target.RetrievalState.PickedUp;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
void TrySetRetrievalState(Target.RetrievalState retrievalState)
|
||||
{
|
||||
if (retrievalState < target.State) { return; }
|
||||
bool wasRetrieved = false;
|
||||
if (retrievalState < target.State || target.State == retrievalState) { return; }
|
||||
bool wasRetrieved = target.Retrieved;
|
||||
target.State = retrievalState;
|
||||
//increment the mission state if the target became retrieved
|
||||
if (!wasRetrieved && target.Retrieved) { State = i + 1; }
|
||||
|
||||
@@ -244,7 +244,12 @@ namespace Barotrauma
|
||||
float dist = Vector2.DistanceSquared(pos, refSub.WorldPosition);
|
||||
foreach (Submarine sub in Submarine.Loaded)
|
||||
{
|
||||
if (sub.Info.Type != SubmarineType.Player && sub != GameMain.NetworkMember?.RespawnManager?.RespawnShuttle) { continue; }
|
||||
if (sub.Info.Type != SubmarineType.Player &&
|
||||
sub.Info.Type != SubmarineType.EnemySubmarine &&
|
||||
sub != GameMain.NetworkMember?.RespawnManager?.RespawnShuttle)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
float minDistToSub = GetMinDistanceToSub(sub);
|
||||
if (dist < minDistToSub * minDistToSub) { continue; }
|
||||
|
||||
Reference in New Issue
Block a user