Unstable 0.1400.7.0 (Coronavirus edition)

This commit is contained in:
Markus Isberg
2021-07-23 21:01:17 +03:00
parent ee5308b39f
commit 47707c824a
133 changed files with 1310 additions and 533 deletions
@@ -10,8 +10,8 @@ namespace Barotrauma
[Serialize("", true)]
public string NPCTag { get; set; }
[Serialize(0, true)]
public int TeamTag { get; set; }
[Serialize(CharacterTeamType.None, true)]
public CharacterTeamType TeamTag { get; set; }
[Serialize(false, true)]
public bool AddToCrew { get; set; }
@@ -29,11 +29,10 @@ namespace Barotrauma
affectedNpcs = ParentEvent.GetTargets(NPCTag).Where(c => c is Character).Select(c => c as Character).ToList();
foreach (var npc in affectedNpcs)
{
CharacterTeamType newTeam = (CharacterTeamType)TeamTag;
// characters will still remain on friendlyNPC team for rest of the tick
npc.SetOriginalTeam(newTeam);
npc.SetOriginalTeam(TeamTag);
if (AddToCrew && (newTeam == CharacterTeamType.Team1 || newTeam == CharacterTeamType.Team2))
if (AddToCrew && (TeamTag == CharacterTeamType.Team1 || TeamTag == CharacterTeamType.Team2))
{
npc.Info.StartItemsGiven = true;
@@ -44,11 +43,11 @@ namespace Barotrauma
var wifiComponent = item.GetComponent<Items.Components.WifiComponent>();
if (wifiComponent != null)
{
wifiComponent.TeamID = newTeam;
wifiComponent.TeamID = TeamTag;
}
}
#if SERVER
GameMain.NetworkMember.CreateEntityEvent(npc, new object[] { NetEntityEvent.Type.AddToCrew, newTeam, npc.Inventory.AllItems.Select(it => it.ID).ToArray() });
GameMain.NetworkMember.CreateEntityEvent(npc, new object[] { NetEntityEvent.Type.AddToCrew, TeamTag, npc.Inventory.AllItems.Select(it => it.ID).ToArray() });
#endif
}
}
@@ -124,13 +124,24 @@ namespace Barotrauma
}
MTRandom rand = new MTRandom(seed);
var initialEventSet = SelectRandomEvents(EventSet.List, rand);
EventSet initialEventSet = SelectRandomEvents(EventSet.List, rand);
EventSet additiveSet = null;
if (initialEventSet != null && initialEventSet.Additive)
{
additiveSet = initialEventSet;
initialEventSet = SelectRandomEvents(EventSet.List.FindAll(e => !e.Additive), rand);
}
if (initialEventSet != null)
{
pendingEventSets.Add(initialEventSet);
CreateEvents(initialEventSet, rand);
}
if (additiveSet != null)
{
pendingEventSets.Add(additiveSet);
CreateEvents(additiveSet, rand);
}
if (level?.LevelData?.Type == LevelData.LevelType.Outpost)
{
//if the outpost is connected to a locked connection, create an event to unlock it
@@ -94,6 +94,8 @@ namespace Barotrauma
public readonly bool TriggerEventCooldown;
public readonly bool Additive;
public readonly Dictionary<string, float> Commonness;
public readonly List<(EventPrefab prefab, float commonness, float probability)> EventPrefabs;
@@ -117,6 +119,8 @@ namespace Barotrauma
MinLevelDifficulty = element.GetAttributeFloat("minleveldifficulty", 0);
MaxLevelDifficulty = Math.Max(element.GetAttributeFloat("maxleveldifficulty", 100), MinLevelDifficulty);
Additive = element.GetAttributeBool("additive", false);
string levelTypeStr = element.GetAttributeString("leveltype", "LocationConnection");
if (!Enum.TryParse(levelTypeStr, true, out LevelType))
{
@@ -24,6 +24,8 @@ namespace Barotrauma
private Submarine sub;
private readonly List<CargoMission> previouslySelectedMissions = new List<CargoMission>();
public override string Description
{
get
@@ -42,7 +44,13 @@ namespace Barotrauma
{
this.sub = sub;
itemConfig = prefab.ConfigElement.Element("Items");
requiredDeliveryAmount = Math.Min(prefab.ConfigElement.GetAttributeFloat("requireddeliveryamount", 0.98f), 1.0f);
requiredDeliveryAmount = Math.Min(prefab.ConfigElement.GetAttributeFloat("requireddeliveryamount", 0.98f), 1.0f);
//this can get called between rounds when the client receives a campaign save
//don't attempt to determine cargo if the sub hasn't been fully loaded
if (sub == null || sub.Loading || sub.Removed || Submarine.Unloading)
{
return;
}
DetermineCargo();
}
@@ -58,6 +66,30 @@ namespace Barotrauma
List<(ItemContainer container, int freeSlots)> containers = sub.GetCargoContainers();
containers.Sort((c1, c2) => { return c2.container.Capacity.CompareTo(c1.container.Capacity); });
previouslySelectedMissions.Clear();
if (GameMain.GameSession?.StartLocation?.SelectedMissions != null)
{
bool isPriorMission = true;
foreach (Mission mission in GameMain.GameSession.StartLocation.SelectedMissions)
{
if (!(mission is CargoMission otherMission)) { continue; }
if (mission == this) { isPriorMission = false; }
previouslySelectedMissions.Add(otherMission);
if (!isPriorMission) { continue; }
foreach (var (element, container) in otherMission.itemsToSpawn)
{
for (int i = 0; i < containers.Count; i++)
{
if (containers[i].container == container)
{
containers[i] = (containers[i].container, containers[i].freeSlots - 1);
break;
}
}
}
}
}
maxItemCount = 0;
foreach (XElement subElement in itemConfig.Elements())
{
@@ -87,9 +119,9 @@ namespace Barotrauma
}
calculatedReward = 0;
foreach (var itemToSpawn in itemsToSpawn)
foreach (var (element, container) in itemsToSpawn)
{
int price = itemToSpawn.element.GetAttributeInt("reward", Prefab.Reward / itemsToSpawn.Count);
int price = element.GetAttributeInt("reward", Prefab.Reward / itemsToSpawn.Count);
if (rewardPerCrate.HasValue)
{
if (price != rewardPerCrate.Value) { rewardPerCrate = -1; }
@@ -108,7 +140,28 @@ namespace Barotrauma
public override int GetReward(Submarine sub)
{
if (sub != this.sub)
bool missionsChanged = false;
if (GameMain.GameSession?.StartLocation?.SelectedMissions != null)
{
List<Mission> currentMissions = GameMain.GameSession.StartLocation.SelectedMissions.Where(m => m is CargoMission).ToList();
if (currentMissions.Count != previouslySelectedMissions.Count)
{
missionsChanged = true;
}
else
{
for (int i = 0; i < previouslySelectedMissions.Count; i++)
{
if (previouslySelectedMissions[i] != currentMissions[i])
{
missionsChanged = true;
break;
}
}
}
}
if (sub != this.sub || missionsChanged)
{
this.sub = sub;
DetermineCargo();
@@ -183,7 +183,7 @@ namespace Barotrauma
}
}
public virtual void SetDifficulty(float difficulty) { }
public virtual void SetLevel(LevelData level) { }
public static Mission LoadRandom(Location[] locations, string seed, bool requireCorrectLocationType, MissionType missionType, bool isSinglePlayer = false)
{
@@ -423,13 +423,16 @@ namespace Barotrauma
protected Character CreateHuman(HumanPrefab humanPrefab, List<Character> characters, Dictionary<Character, List<Item>> characterItems, Submarine submarine, CharacterTeamType teamType, ISpatialEntity positionToStayIn = null, Rand.RandSync humanPrefabRandSync = Rand.RandSync.Server, bool giveTags = true)
{
if (positionToStayIn == null)
{
positionToStayIn = WayPoint.GetRandom(SpawnType.Human, null, submarine);
}
var characterInfo = humanPrefab.GetCharacterInfo(Rand.RandSync.Server) ?? new CharacterInfo(CharacterPrefab.HumanSpeciesName, npcIdentifier: humanPrefab.Identifier, jobPrefab: humanPrefab.GetJobPrefab(humanPrefabRandSync), randSync: humanPrefabRandSync);
characterInfo.TeamID = teamType;
if (positionToStayIn == null)
{
positionToStayIn =
WayPoint.GetRandom(SpawnType.Human, characterInfo.Job?.Prefab, submarine) ??
WayPoint.GetRandom(SpawnType.Human, null, submarine);
}
Character spawnedCharacter = Character.Create(characterInfo.SpeciesName, positionToStayIn.WorldPosition, ToolBox.RandomSeed(8), characterInfo, createNetworkEvent: false);
spawnedCharacter.Prefab = humanPrefab;
humanPrefab.InitializeCharacter(spawnedCharacter, positionToStayIn);
@@ -107,7 +107,7 @@ namespace Barotrauma
//ruin/cave/wreck items are allowed to spawn close to the sub
float minDistance = spawnPositionType == Level.PositionType.Ruin || spawnPositionType == Level.PositionType.Cave || spawnPositionType == Level.PositionType.Wreck ?
0.0f : Level.Loaded.Size.X * 0.3f;
nestPosition = Level.Loaded.GetRandomItemPos(spawnPositionType, 100.0f, minDistance, 30.0f);
Level.Loaded.TryGetInterestingPosition(true, spawnPositionType, 0.0f, out Vector2 nestPosition);
List<GraphEdge> spawnEdges = new List<GraphEdge>();
if (spawnPositionType == Level.PositionType.Cave)
{
@@ -28,6 +28,8 @@ namespace Barotrauma
private float pirateSightingUpdateTimer;
private Vector2? lastSighting;
private LevelData levelData;
public override int TeamCount => 2;
private bool outsideOfSonarRange;
@@ -83,21 +85,24 @@ namespace Barotrauma
characterTypeConfig = prefab.ConfigElement.Element("CharacterTypes");
addedMissionDifficultyPerPlayer = prefab.ConfigElement.GetAttributeFloat("addedmissiondifficultyperplayer", 0);
// for campaign missions, set difficulty at construction
// for campaign missions, set level at construction
LevelData levelData = locations[0].Connections.Where(c => c.Locations.Contains(locations[1])).FirstOrDefault()?.LevelData ?? locations[0]?.LevelData;
SetDifficulty(levelData?.Difficulty ?? Level.Loaded?.Difficulty ?? 0f);
if (levelData != null)
{
SetLevel(levelData);
}
}
public override void SetDifficulty(float difficulty)
public override void SetLevel(LevelData level)
{
if (missionDifficulty > 0f)
if (levelData != null)
{
// difficulty already set
//level already set
return;
}
missionDifficulty = difficulty;
levelData = level;
missionDifficulty = level?.Difficulty ?? 0;
XElement submarineConfig = GetRandomDifficultyModifiedElement(submarineTypeConfig, missionDifficulty, ShipRandomnessModifier);
@@ -123,23 +128,24 @@ namespace Barotrauma
submarineInfo = new SubmarineInfo(contentFile.Path);
}
private float GetDifficultyModifiedValue(float preferredDifficulty, float levelDifficulty, float randomnessModifier)
private float GetDifficultyModifiedValue(float preferredDifficulty, float levelDifficulty, float randomnessModifier, Random rand)
{
return Math.Abs(levelDifficulty - preferredDifficulty + (Rand.Range(-randomnessModifier, randomnessModifier, Rand.RandSync.Server)));
return Math.Abs(levelDifficulty - preferredDifficulty + MathHelper.Lerp(-randomnessModifier, randomnessModifier, (float)rand.NextDouble()));
}
private int GetDifficultyModifiedAmount(int minAmount, int maxAmount, float levelDifficulty)
private int GetDifficultyModifiedAmount(int minAmount, int maxAmount, float levelDifficulty, Random rand)
{
return Math.Max((int)Math.Round(minAmount + (maxAmount - minAmount) * ((levelDifficulty + Rand.Range(-RandomnessModifier, RandomnessModifier, Rand.RandSync.Server)) / MaxDifficulty)), minAmount);
return Math.Max((int)Math.Round(minAmount + (maxAmount - minAmount) * (levelDifficulty + MathHelper.Lerp(-RandomnessModifier, RandomnessModifier, (float)rand.NextDouble())) / MaxDifficulty), minAmount);
}
private XElement GetRandomDifficultyModifiedElement(XElement parentElement, float levelDifficulty, float randomnessModifier)
{
Random rand = new MTRandom(ToolBox.StringToInt(levelData.Seed));
// look for the element that is closest to our difficulty, with some randomness
XElement bestElement = null;
float bestValue = float.MaxValue;
foreach (XElement element in parentElement.Elements())
{
float applicabilityValue = GetDifficultyModifiedValue(element.GetAttributeFloat(0f, "preferreddifficulty"), levelDifficulty, randomnessModifier);
float applicabilityValue = GetDifficultyModifiedValue(element.GetAttributeFloat(0f, "preferreddifficulty"), levelDifficulty, randomnessModifier, rand);
if (applicabilityValue < bestValue)
{
bestElement = element;
@@ -154,11 +160,11 @@ namespace Barotrauma
Vector2 patrolPos = enemySub.WorldPosition;
Point subSize = enemySub.GetDockedBorders().Size;
if (!Level.Loaded.TryGetInterestingPosition(true, Level.PositionType.MainPath | Level.PositionType.SidePath, Level.Loaded.Size.X * 0.3f, out preferredSpawnPos))
if (!Level.Loaded.TryGetInterestingPosition(true, Level.PositionType.MainPath, Level.Loaded.Size.X * 0.3f, out preferredSpawnPos))
{
DebugConsole.ThrowError("Could not spawn pirate submarine in an interesting location! " + this);
}
if (!Level.Loaded.TryGetInterestingPositionAwayFromPoint(true, Level.PositionType.MainPath | Level.PositionType.SidePath, Level.Loaded.Size.X * 0.3f, out patrolPos, preferredSpawnPos, minDistFromPoint: 10000f))
if (!Level.Loaded.TryGetInterestingPositionAwayFromPoint(true, Level.PositionType.MainPath, Level.Loaded.Size.X * 0.3f, out patrolPos, preferredSpawnPos, minDistFromPoint: 10000f))
{
DebugConsole.ThrowError("Could not give pirate submarine an interesting location to patrol to! " + this);
}
@@ -182,7 +188,7 @@ namespace Barotrauma
}
}
private void InitPirateShip(Vector2 spawnPos)
private void InitPirateShip()
{
enemySub.NeutralizeBallast();
if (enemySub.GetItems(alsoFromConnectedSubs: false).Find(i => i.HasTag("reactor") && !i.NonInteractable)?.GetComponent<Reactor>() is Reactor reactor)
@@ -193,6 +199,7 @@ namespace Barotrauma
enemySub.TeamID = CharacterTeamType.None;
//make the enemy sub withstand atleast the same depth as the player sub
enemySub.RealWorldCrushDepth = Math.Max(enemySub.RealWorldCrushDepth, Submarine.MainSub.RealWorldCrushDepth);
enemySub.ImmuneToBallastFlora = true;
}
private void InitPirates()
@@ -214,12 +221,14 @@ namespace Barotrauma
float enemyCreationDifficulty = missionDifficulty + playerCount * addedMissionDifficultyPerPlayer;
Random rand = new MTRandom(ToolBox.StringToInt(levelData.Seed));
bool commanderAssigned = false;
foreach (XElement element in characterConfig.Elements())
{
// it is possible to get more than the "max" amount of characters if the modified difficulty is high enough; this is intentional
// if necessary, another "hard max" value could be used to clamp the value for performance/gameplay concerns
int amountCreated = GetDifficultyModifiedAmount(element.GetAttributeInt("minamount", 0), element.GetAttributeInt("maxamount", 0), enemyCreationDifficulty);
int amountCreated = GetDifficultyModifiedAmount(element.GetAttributeInt("minamount", 0), element.GetAttributeInt("maxamount", 0), enemyCreationDifficulty, rand);
for (int i = 0; i < amountCreated; i++)
{
XElement characterType = characterTypeConfig.Elements().Where(e => e.GetAttributeString("typeidentifier", string.Empty) == element.GetAttributeString("typeidentifier", string.Empty)).FirstOrDefault();
@@ -307,7 +316,7 @@ namespace Barotrauma
#endif
if (!IsClient)
{
InitPirateShip(spawnPos);
InitPirateShip();
}
enemySub.SetPosition(spawnPos);