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
@@ -300,9 +300,9 @@ namespace Barotrauma
if (containedItem == null) { continue; }
if (predicate == null || predicate(containedItem))
{
if (character.Submarine != Submarine.MainSub && avoidDroppingInSea)
if (avoidDroppingInSea && !character.IsInFriendlySub)
{
// If we are outside of main sub, try to put the item in the inventory instead dropping it in the sea.
// If we are not inside a friendly sub (= same team), try to put the item in the inventory instead dropping it.
if (character.Inventory.TryPutItem(containedItem, character, CharacterInventory.anySlot))
{
continue;
@@ -2595,7 +2595,7 @@ namespace Barotrauma
{
if ((SelectedAiTarget != null || wallTarget != null) && IsLatchedOnSub)
{
if (!(SelectedAiTarget.Entity is Structure wall))
if (!(SelectedAiTarget?.Entity is Structure wall))
{
wall = wallTarget?.Structure;
}
@@ -475,14 +475,16 @@ namespace Barotrauma
bool needsGear = NeedsDivingGear(Character.CurrentHull, out _);
if (!needsGear || oxygenLow)
{
bool shouldKeepTheGearOn =
bool isCurrentObjectiveFindSafety = ObjectiveManager.IsCurrentObjective<AIObjectiveFindSafety>();
bool shouldKeepTheGearOn =
isCurrentObjectiveFindSafety ||
Character.AnimController.InWater ||
Character.AnimController.HeadInWater ||
Character.CurrentHull == null ||
(Character.Submarine?.TeamID != Character.TeamID && !Character.IsEscorted) || // these instances should maybe be combined to a method
ObjectiveManager.IsCurrentObjective<AIObjectiveFindSafety>() ||
Character.Submarine == null ||
(Character.Submarine.TeamID != Character.TeamID && !Character.IsEscorted) ||
ObjectiveManager.CurrentObjective.GetSubObjectivesRecursive(true).Any(o => o.KeepDivingGearOn);
if (oxygenLow && Character.CurrentHull.Oxygen > 0)
if (oxygenLow && Character.CurrentHull.Oxygen > 0 && (!isCurrentObjectiveFindSafety || Character.OxygenAvailable < 1))
{
shouldKeepTheGearOn = false;
}
@@ -1348,13 +1350,15 @@ namespace Barotrauma
/// <summary>
/// Check whether the character has a diving suit in usable condition plus some oxygen.
/// </summary>
public static bool HasDivingSuit(Character character, float conditionPercentage = 0) => HasItem(character, AIObjectiveFindDivingGear.HEAVY_DIVING_GEAR, out _, AIObjectiveFindDivingGear.OXYGEN_SOURCE, conditionPercentage, requireEquipped: true,
predicate: (Item item) => { return character.HasEquippedItem(item, InvSlotType.OuterClothes); });
public static bool HasDivingSuit(Character character, float conditionPercentage = 0)
=> HasItem(character, AIObjectiveFindDivingGear.HEAVY_DIVING_GEAR, out _, AIObjectiveFindDivingGear.OXYGEN_SOURCE, conditionPercentage, requireEquipped: true,
predicate: (Item item) => character.HasEquippedItem(item, InvSlotType.OuterClothes));
/// <summary>
/// Check whether the character has a diving mask in usable condition plus some oxygen.
/// </summary>
public static bool HasDivingMask(Character character, float conditionPercentage = 0) => HasItem(character, AIObjectiveFindDivingGear.LIGHT_DIVING_GEAR, out _, AIObjectiveFindDivingGear.OXYGEN_SOURCE, conditionPercentage, requireEquipped: true);
public static bool HasDivingMask(Character character, float conditionPercentage = 0)
=> HasItem(character, AIObjectiveFindDivingGear.LIGHT_DIVING_GEAR, out _, AIObjectiveFindDivingGear.OXYGEN_SOURCE, conditionPercentage, requireEquipped: true);
private static List<Item> matchingItems = new List<Item>();
@@ -2048,7 +2052,7 @@ namespace Barotrauma
{
var repairItemsObjective = operatingAI.ObjectiveManager.GetObjective<AIObjectiveRepairItems>();
if (repairItemsObjective == null) { continue; }
if (repairItemsObjective.SubObjectives.None(o => o is AIObjectiveRepairItem repairObjective && repairObjective.Item == target))
if (!(repairItemsObjective.SubObjectives.FirstOrDefault(o => o is AIObjectiveRepairItem) is AIObjectiveRepairItem activeObjective) || activeObjective.Item != target)
{
// Not targeting the same item.
continue;
@@ -133,7 +133,7 @@ namespace Barotrauma
}
else
{
if (ItemToContain.ParentInventory == character.Inventory && character.Submarine == Submarine.MainSub)
if (ItemToContain.ParentInventory == character.Inventory && character.IsInFriendlySub)
{
ItemToContain.Drop(character);
}
@@ -53,7 +53,7 @@ namespace Barotrauma
if (HumanAIController.NeedsDivingGear(character.CurrentHull, out bool needsSuit) &&
(needsSuit ?
!HumanAIController.HasDivingSuit(character, conditionPercentage: AIObjectiveFindDivingGear.MIN_OXYGEN) :
!HumanAIController.HasDivingMask(character, conditionPercentage: AIObjectiveFindDivingGear.MIN_OXYGEN)))
!HumanAIController.HasDivingGear(character, conditionPercentage: AIObjectiveFindDivingGear.MIN_OXYGEN)))
{
Priority = 100;
}
@@ -108,6 +108,7 @@ namespace Barotrauma
void ReportWeldingFuelTankCount()
{
if (character.Submarine != Submarine.MainSub) { return; }
int remainingOxygenTanks = Submarine.MainSub.GetItems(false).Count(i => i.HasTag("weldingfuel") && i.Condition > 1);
if (remainingOxygenTanks == 0)
{
@@ -131,7 +132,7 @@ namespace Barotrauma
Abandon = true;
return;
}
Vector2 toLeak = Leak.WorldPosition - character.WorldPosition;
Vector2 toLeak = Leak.WorldPosition - character.AnimController.AimSourceWorldPos;
// TODO: use the collider size/reach?
if (!character.AnimController.InWater && Math.Abs(toLeak.X) < 100 && toLeak.Y < 0.0f && toLeak.Y > -150)
{
@@ -157,6 +158,7 @@ namespace Barotrauma
{
TryAddSubObjective(ref gotoObjective, () => new AIObjectiveGoTo(Leak, character, objectiveManager)
{
UseDistanceRelativeToAimSourcePos = true,
CloseEnough = reach,
DialogueIdentifier = Leak.FlowTargetHull != null ? "dialogcannotreachleak" : null,
TargetName = Leak.FlowTargetHull?.DisplayName,
@@ -165,7 +167,7 @@ namespace Barotrauma
onAbandon: () =>
{
if (CheckObjectiveSpecific()) { IsCompleted = true; }
else if ((Leak.WorldPosition - character.WorldPosition).LengthSquared() > MathUtils.Pow(reach * 2, 2))
else if ((Leak.WorldPosition - character.AnimController.AimSourceWorldPos).LengthSquared() > MathUtils.Pow(reach * 2, 2))
{
// Too far
Abandon = true;
@@ -66,6 +66,11 @@ namespace Barotrauma
public bool AlwaysUseEuclideanDistance { get; set; } = true;
/// <summary>
/// If true, the distance to the destination is calculated from the character's AimSourcePos (= shoulder) instead of the collider's position
/// </summary>
public bool UseDistanceRelativeToAimSourcePos { get; set; } = false;
public override bool AbandonWhenCannotCompleteSubjectives => !repeat;
public override bool AllowOutsideSubmarine => AllowGoingOutside;
@@ -589,7 +594,9 @@ namespace Barotrauma
float xDiff = Math.Abs(Target.WorldPosition.X - character.WorldPosition.X);
return xDiff <= CloseEnough;
}
return Vector2.DistanceSquared(Target.WorldPosition, character.WorldPosition) < CloseEnough * CloseEnough;
Vector2 sourcePos = UseDistanceRelativeToAimSourcePos ? character.AnimController.AimSourceWorldPos : character.WorldPosition;
return Vector2.DistanceSquared(Target.WorldPosition, sourcePos) < CloseEnough * CloseEnough;
}
}
@@ -215,7 +215,9 @@ namespace Barotrauma
var objective = new AIObjectiveGoTo(Item, character, objectiveManager)
{
// Don't stop in ladders, because we can't interact with other items while holding the ladders.
endNodeFilter = node => node.Waypoint.Ladders == null
endNodeFilter = node => node.Waypoint.Ladders == null,
// Allow repairing hatches and airlock doors.
AllowGoingOutside = HumanAIController.ObjectiveManager.IsCurrentOrder<AIObjectiveRepairItems>() && Item.GetComponent<Door>() != null
};
if (repairTool != null)
{
@@ -82,6 +82,7 @@ namespace Barotrauma
public static bool ViableForRepair(Item item, Character character, HumanAIController humanAIController)
{
if (!IsValidTarget(item, character)) { return false; }
if (item.CurrentHull == null) { return true; }
if (item.CurrentHull.FireSources.Count > 0) { return false; }
// Don't repair items in rooms that have enemies inside.
if (Character.CharacterList.Any(c => c.CurrentHull == item.CurrentHull && !humanAIController.IsFriendly(c) && HumanAIController.IsActive(c))) { return false; }
@@ -150,7 +151,6 @@ namespace Barotrauma
if (item.IgnoreByAI(character)) { return false; }
if (!item.IsInteractable(character)) { return false; }
if (item.IsFullCondition) { return false; }
if (item.CurrentHull == null) { return false; }
if (item.Submarine == null || character.Submarine == null) { return false; }
//player crew ignores items in outposts
if (character.IsOnPlayerTeam && item.Submarine.Info.IsOutpost) { return false; }
@@ -234,8 +234,6 @@ namespace Barotrauma
new string[2] { targetCharacter.Name, targetCharacter.CurrentHull.DisplayName }, new bool[2] { false, true }),
null, 1.0f, "foundwoundedtarget" + targetCharacter.Name, 60.0f);
}
character.SelectCharacter(targetCharacter);
}
GiveTreatment(deltaTime);
}
@@ -268,6 +266,8 @@ namespace Barotrauma
}
treatmentTimer = TreatmentDelay;
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);
@@ -282,6 +282,7 @@ namespace Barotrauma
{
Item matchingItem = character.Inventory.FindItemByIdentifier(treatmentSuitability.Key, true);
if (matchingItem == null) { continue; }
character.SelectCharacter(targetCharacter);
ApplyTreatment(affliction, matchingItem);
//wait a bit longer after applying a treatment to wait for potential side-effects to manifest
treatmentTimer = TreatmentDelay * 4;
@@ -292,7 +293,6 @@ namespace Barotrauma
// Find treatments outside of own inventory only if inside the own sub.
if (character.Submarine != null && character.Submarine.TeamID == character.TeamID)
{
float cprSuitability = targetCharacter.Oxygen < 0.0f ? -targetCharacter.Oxygen * 100.0f : 0.0f;
//didn't have any suitable treatments available, try to find some medical items
if (currentTreatmentSuitabilities.Any(s => s.Value > cprSuitability))
{
@@ -329,7 +329,6 @@ namespace Barotrauma
new string[2] { targetCharacter.Name, itemListStr }, new bool[2] { false, true }),
null, 2.0f, "listrequiredtreatments" + targetCharacter.Name, 60.0f);
}
character.DeselectCharacter();
RemoveSubObjective(ref getItemObjective);
TryAddSubObjective(ref getItemObjective,
constructor: () => new AIObjectiveGetItem(character, suitableItemIdentifiers.ToArray(), objectiveManager, equip: true, spawnItemIfNotFound: character.TeamID == CharacterTeamType.FriendlyNPC),
@@ -345,9 +344,24 @@ namespace Barotrauma
}
}
}
else if (!targetCharacter.IsUnconscious)
{
//no suitable treatments found, not inside our own sub (= can't search for more treatments), the target isn't unconscious (= can't give CPR)
// -> abandon
Abandon = true;
return;
}
if (character != targetCharacter)
{
character.AnimController.Anim = AnimController.Animation.CPR;
if (cprSuitability > 0.0f)
{
character.SelectCharacter(targetCharacter);
character.AnimController.Anim = AnimController.Animation.CPR;
}
else
{
character.DeselectCharacter();
}
}
}
@@ -63,7 +63,7 @@ namespace Barotrauma
allItems = Wreck.GetItems(false);
thalamusItems = allItems.FindAll(i => IsThalamus(i.prefab));
hulls.AddRange(Wreck.GetHulls(false));
var potentialBrainHulls = new Dictionary<Hull, float>();
var potentialBrainHulls = new List<(Hull hull, float weight)>();
brain = new Item(brainPrefab, Vector2.Zero, Wreck);
thalamusItems.Add(brain);
Point minSize = brain.Rect.Size.Multiply(brain.Scale);
@@ -100,10 +100,10 @@ namespace Barotrauma
}
if (weight > 0)
{
potentialBrainHulls.TryAdd(hull, weight);
potentialBrainHulls.Add((hull, weight));
}
}
Hull brainHull = ToolBox.SelectWeightedRandom(potentialBrainHulls.Keys.ToList(), potentialBrainHulls.Values.ToList(), Rand.RandSync.Server);
Hull brainHull = ToolBox.SelectWeightedRandom(potentialBrainHulls.Select(pbh => pbh.hull).ToList(), potentialBrainHulls.Select(pbh => pbh.weight).ToList(), Rand.RandSync.Server);
var thalamusStructurePrefabs = StructurePrefab.Prefabs.Where(p => IsThalamus(p));
if (brainHull == null)
{
@@ -187,8 +187,11 @@ namespace Barotrauma
if (!spawnOrgans.Contains(item))
{
spawnOrgans.Add(item);
// Try to flood the hull so that the spawner won't die.
item.CurrentHull.WaterVolume = item.CurrentHull.Volume;
if (item.CurrentHull != null)
{
// Try to flood the hull so that the spawner won't die.
item.CurrentHull.WaterVolume = item.CurrentHull.Volume;
}
}
}
}
@@ -108,6 +108,16 @@ namespace Barotrauma
public enum Animation { None, Climbing, UsingConstruction, Struggle, CPR };
public Animation Anim;
public Vector2 AimSourceWorldPos
{
get
{
Vector2 sourcePos = character.AnimController.AimSourcePos;
if (character.Submarine != null) { sourcePos += character.Submarine.Position; }
return sourcePos;
}
}
public Vector2 AimSourcePos => ConvertUnits.ToDisplayUnits(AimSourceSimPos);
public virtual Vector2 AimSourceSimPos => Collider.SimPosition;
@@ -1463,7 +1463,7 @@ namespace Barotrauma
target.CharacterHealth.CalculateVitality();
if (wasCritical && target.Vitality > 0.0f && Timing.TotalTime > lastReviveTime + 10.0f)
{
character.Info.IncreaseSkillLevel("medical", SkillSettings.Current.SkillIncreasePerCprRevive, character.Position + Vector2.UnitY * 150.0f);
character.Info?.IncreaseSkillLevel("medical", SkillSettings.Current.SkillIncreasePerCprRevive, character.Position + Vector2.UnitY * 150.0f);
SteamAchievementManager.OnCharacterRevived(target, character);
lastReviveTime = (float)Timing.TotalTime;
#if SERVER
@@ -576,7 +576,7 @@ namespace Barotrauma
get { return pressureProtection; }
set
{
pressureProtection = Math.Max(value, 0.0f);
pressureProtection = Math.Max(value, pressureProtection);
pressureProtectionLastSet = Timing.TotalTime;
}
}
@@ -882,6 +882,8 @@ namespace Barotrauma
}
}
public bool IsInFriendlySub => Submarine != null && Submarine.TeamID == TeamID;
public delegate void OnDeathHandler(Character character, CauseOfDeath causeOfDeath);
public OnDeathHandler OnDeath;
@@ -2065,10 +2067,9 @@ namespace Barotrauma
if (!CanInteract || inventory.Locked) { return false; }
//the inventory belongs to some other character
if (inventory.Owner is Character && inventory.Owner != this)
if (inventory.Owner is Character character && inventory.Owner != this)
{
var owner = (Character)inventory.Owner;
var owner = character;
//can only be accessed if the character is incapacitated and has been selected
return SelectedCharacter == owner && owner.CanInventoryBeAccessed;
}
@@ -2361,7 +2362,7 @@ namespace Barotrauma
#if CLIENT
if (isLocalPlayer)
{
if (!IsMouseOnUI)
if (!IsMouseOnUI && (ViewTarget == null || ViewTarget == this))
{
if (findFocusedTimer <= 0.0f || Screen.Selected == GameMain.SubEditorScreen)
{
@@ -2832,7 +2833,7 @@ namespace Barotrauma
{
if (Timing.TotalTime > pressureProtectionLastSet + 0.1)
{
PressureProtection = 0.0f;
pressureProtection = 0.0f;
}
}
if (NeedsWater)
@@ -2994,10 +2995,7 @@ namespace Barotrauma
{
despawnTimer = GameMain.Config.CorpseDespawnDelay;
UpdateDespawn(1.0f, ignoreThresholds: true);
if (createNetworkEvents)
{
Spawner.Update();
}
Spawner.Update(createNetworkEvents);
}
public static void RemoveByPrefab(CharacterPrefab prefab)
@@ -3526,6 +3524,7 @@ namespace Barotrauma
}
bool wasDead = IsDead;
Vector2 simPos = hitLimb.SimPosition + ConvertUnits.ToSimUnits(dir);
float prevVitality = CharacterHealth.Vitality;
AttackResult attackResult = hitLimb.AddDamage(simPos, afflictions, playSound, damageMultiplier: damageMultiplier, penetration: penetration);
CharacterHealth.ApplyDamage(hitLimb, attackResult, allowStacking);
if (attacker != this)
@@ -3534,7 +3533,7 @@ namespace Barotrauma
OnAttackedProjSpecific(attacker, attackResult, stun);
if (!wasDead)
{
TryAdjustAttackerSkill(attacker, -attackResult.Damage);
TryAdjustAttackerSkill(attacker, CharacterHealth.Vitality - prevVitality);
if (IsDead)
{
attacker?.RecordKill(this);
@@ -4001,7 +4000,7 @@ namespace Barotrauma
}
else
{
canBePutInOriginalInventory = inventory.CanBePut(newItem, slotIndices[0]);
canBePutInOriginalInventory = inventory.CanBePut(newItem, slotIndices[0], ignoreCondition: true);
}
if (canBePutInOriginalInventory)
@@ -97,7 +97,7 @@ namespace Barotrauma
State = InfectionState.Final;
ActivateHusk();
ApplyDamage(deltaTime, applyForce: true);
character.SetStun(1);
character.SetStun(5);
}
}