v1.4.4.1 (Blood in the Water Update)
This commit is contained in:
@@ -147,8 +147,8 @@ namespace Barotrauma
|
||||
/// <summary>
|
||||
/// Is the character player or does it have an active ship command manager (an AI controlled sub)? Bots in the player team are not treated as commanders.
|
||||
/// </summary>
|
||||
public bool IsCommanding => IsPlayer || (AIController is HumanAIController humanAI && humanAI.ShipCommandManager != null && humanAI.ShipCommandManager.Active);
|
||||
public bool IsBot => !IsPlayer && AIController is HumanAIController humanAI && humanAI.Enabled;
|
||||
public bool IsCommanding => IsPlayer || AIController is HumanAIController { ShipCommandManager.Active: true };
|
||||
public bool IsBot => !IsPlayer && AIController is HumanAIController { Enabled: true };
|
||||
public bool IsEscorted { get; set; }
|
||||
public Identifier JobIdentifier => Info?.Job?.Prefab.Identifier ?? Identifier.Empty;
|
||||
|
||||
@@ -349,7 +349,13 @@ namespace Barotrauma
|
||||
|
||||
public bool IsFriendlyNPCTurnedHostile => originalTeamID == CharacterTeamType.FriendlyNPC && teamID == CharacterTeamType.Team2;
|
||||
|
||||
public bool IsInstigator => CombatAction != null && CombatAction.IsInstigator;
|
||||
public bool IsInstigator => CombatAction is { IsInstigator: true };
|
||||
|
||||
/// <summary>
|
||||
/// Set true only, if the character is turned hostile from an escort mission (See <see cref="EscortMission"/>).
|
||||
/// </summary>
|
||||
public bool IsHostileEscortee;
|
||||
|
||||
public CombatAction CombatAction;
|
||||
|
||||
public readonly AnimController AnimController;
|
||||
@@ -393,8 +399,10 @@ namespace Barotrauma
|
||||
public readonly CharacterPrefab Prefab;
|
||||
|
||||
public readonly CharacterParams Params;
|
||||
|
||||
|
||||
public Identifier SpeciesName => Params?.SpeciesName ?? "null".ToIdentifier();
|
||||
|
||||
public Identifier GetBaseCharacterSpeciesName() => Prefab.GetBaseCharacterSpeciesName(SpeciesName);
|
||||
|
||||
public Identifier Group => HumanPrefab is HumanPrefab humanPrefab && !humanPrefab.Group.IsEmpty ? humanPrefab.Group : Params.Group;
|
||||
|
||||
@@ -444,6 +452,17 @@ namespace Barotrauma
|
||||
set => Params.Visibility = value;
|
||||
}
|
||||
|
||||
public float MaxPerceptionDistance
|
||||
{
|
||||
get => Params.AI?.MaxPerceptionDistance ?? 0;
|
||||
set
|
||||
{
|
||||
if (Params.AI != null)
|
||||
{
|
||||
Params.AI.MaxPerceptionDistance = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
public bool IsTraitor
|
||||
{
|
||||
get;
|
||||
@@ -583,9 +602,6 @@ namespace Barotrauma
|
||||
|
||||
public CharacterInventory Inventory { get; private set; }
|
||||
|
||||
private Color speechBubbleColor;
|
||||
private float speechBubbleTimer;
|
||||
|
||||
/// <summary>
|
||||
/// Prevents the character from interacting with items or characters
|
||||
/// </summary>
|
||||
@@ -685,7 +701,8 @@ namespace Barotrauma
|
||||
if (IsPlayer && isServerOrSingleplayer && value is { IsDead: true, Wallet: { Balance: var balance and > 0 } grabbedWallet })
|
||||
{
|
||||
#if SERVER
|
||||
if (GameMain.GameSession.Campaign is MultiPlayerCampaign mpCampaign && GameMain.Server is { ServerSettings: { } settings })
|
||||
var mpCampaign = GameMain.GameSession.Campaign as MultiPlayerCampaign;
|
||||
if (mpCampaign != null && GameMain.Server is { ServerSettings: { } settings })
|
||||
{
|
||||
switch (settings.LootedMoneyDestination)
|
||||
{
|
||||
@@ -698,16 +715,28 @@ namespace Barotrauma
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
GameServer.Log($"{GameServer.CharacterLogName(this)} grabbed {value.Name}'s body and received {grabbedWallet.Balance} mk.", ServerLog.MessageType.Money);
|
||||
|
||||
grabbedWallet.Deduct(balance);
|
||||
//we need to save the grabbed character's wallet this at this point to ensure
|
||||
//the client doesn't get to keep the money if they respawn
|
||||
if (mpCampaign != null && selectedCharacter.Info != null)
|
||||
{
|
||||
var characterCampaignData = mpCampaign?.GetCharacterData(selectedCharacter.Info);
|
||||
if (characterCampaignData!= null)
|
||||
{
|
||||
characterCampaignData.WalletData = grabbedWallet.Save();
|
||||
characterCampaignData?.ApplyWalletData(selectedCharacter);
|
||||
}
|
||||
}
|
||||
#elif CLIENT
|
||||
if (GameMain.GameSession.Campaign is SinglePlayerCampaign spCampaign)
|
||||
{
|
||||
spCampaign.Bank.Give(balance);
|
||||
}
|
||||
#endif
|
||||
|
||||
grabbedWallet.Deduct(balance);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -738,6 +767,25 @@ namespace Barotrauma
|
||||
if (item2 != null && item2 != item1) { yield return item2; }
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsDualWieldingRangedWeapons()
|
||||
{
|
||||
int rangedItemCount = 0;
|
||||
foreach (var item in HeldItems)
|
||||
{
|
||||
if (item.GetComponent<RangedWeapon>() != null)
|
||||
{
|
||||
rangedItemCount++;
|
||||
}
|
||||
|
||||
if (rangedItemCount > 1)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private float lowPassMultiplier;
|
||||
public float LowPassMultiplier
|
||||
@@ -844,7 +892,7 @@ namespace Barotrauma
|
||||
|
||||
public float Stun
|
||||
{
|
||||
get { return IsRagdolled && !AnimController.IsHanging ? 1.0f : CharacterHealth.Stun; }
|
||||
get { return IsRagdolled && !AnimController.IsHangingWithRope ? 1.0f : CharacterHealth.Stun; }
|
||||
set
|
||||
{
|
||||
if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient) { return; }
|
||||
@@ -1093,7 +1141,7 @@ namespace Barotrauma
|
||||
{
|
||||
get
|
||||
{
|
||||
return (SelectedItem == null || SelectedItem.GetComponent<Controller>() is { AllowAiming: true }) && !IsIncapacitated && !IsRagdolled;
|
||||
return (SelectedItem == null || SelectedItem.GetComponent<Controller>() is { AllowAiming: true }) && !IsIncapacitated && (!IsRagdolled || AnimController.IsHoldingToRope);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1350,7 +1398,7 @@ namespace Barotrauma
|
||||
}
|
||||
if (Params.VariantFile != null && Params.MainElement is ContentXElement paramsMainElement)
|
||||
{
|
||||
var overrideElement = Params.VariantFile.Root.FromPackage(paramsMainElement.ContentPackage);
|
||||
var overrideElement = Params.VariantFile.GetRootExcludingOverride().FromPackage(paramsMainElement.ContentPackage);
|
||||
// Only override if the override file contains matching elements
|
||||
if (overrideElement.GetChildElement("inventory") != null)
|
||||
{
|
||||
@@ -1432,7 +1480,7 @@ namespace Barotrauma
|
||||
if (ragdollParams == null && prefab.VariantOf == null)
|
||||
{
|
||||
Identifier name = Params.UseHuskAppendage ? nonHuskedSpeciesName : speciesName;
|
||||
ragdollParams = IsHumanoid ? RagdollParams.GetDefaultRagdollParams<HumanRagdollParams>(name) : RagdollParams.GetDefaultRagdollParams<FishRagdollParams>(name) as RagdollParams;
|
||||
ragdollParams = IsHumanoid ? RagdollParams.GetDefaultRagdollParams<HumanRagdollParams>(name, Params, Prefab.ContentPackage) : RagdollParams.GetDefaultRagdollParams<FishRagdollParams>(name, Params, Prefab.ContentPackage);
|
||||
}
|
||||
if (Params.HasInfo && info == null)
|
||||
{
|
||||
@@ -1818,9 +1866,18 @@ namespace Barotrauma
|
||||
// - dragging someone
|
||||
// - crouching
|
||||
// - moving backwards
|
||||
public bool CanRun => (SelectedCharacter == null || !SelectedCharacter.CanBeDragged || HasAbilityFlag(AbilityFlags.MoveNormallyWhileDragging)) &&
|
||||
(!(AnimController is HumanoidAnimController) || !((HumanoidAnimController)AnimController).Crouching) &&
|
||||
!AnimController.IsMovingBackwards && !HasAbilityFlag(AbilityFlags.MustWalk);
|
||||
public bool CanRun => CanRunWhileDragging() &&
|
||||
AnimController is not HumanoidAnimController { Crouching: true } &&
|
||||
!AnimController.IsMovingBackwards && !HasAbilityFlag(AbilityFlags.MustWalk) &&
|
||||
!AnimController.IsHoldingToRope;
|
||||
|
||||
public bool CanRunWhileDragging()
|
||||
{
|
||||
if (selectedCharacter == null || !selectedCharacter.CanBeDragged) { return true; }
|
||||
//if the dragged character is conscious, don't allow running (the dragged character won't keep up, and the dragging gets interrupted)
|
||||
if (!selectedCharacter.IsIncapacitated && selectedCharacter.Stun <= 0.0f) { return false; }
|
||||
return HasAbilityFlag(AbilityFlags.MoveNormallyWhileDragging);
|
||||
}
|
||||
|
||||
public Vector2 ApplyMovementLimits(Vector2 targetMovement, float currentSpeed)
|
||||
{
|
||||
@@ -2212,6 +2269,25 @@ namespace Barotrauma
|
||||
|
||||
if (Inventory != null)
|
||||
{
|
||||
if (IsKeyHit(InputType.DropItem))
|
||||
{
|
||||
foreach (Item item in HeldItems)
|
||||
{
|
||||
if (!CanInteractWith(item)) { continue; }
|
||||
|
||||
if (SelectedItem?.OwnInventory != null && SelectedItem.OwnInventory.CanBePut(item))
|
||||
{
|
||||
SelectedItem.OwnInventory.TryPutItem(item, this);
|
||||
}
|
||||
else
|
||||
{
|
||||
item.Drop(this);
|
||||
}
|
||||
//only drop one held item per key hit
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool CanUseItemsWhenSelected(Item item) => item == null || !item.Prefab.DisableItemUsageWhenSelected;
|
||||
if (CanUseItemsWhenSelected(SelectedItem) && CanUseItemsWhenSelected(SelectedSecondaryItem))
|
||||
{
|
||||
@@ -2525,7 +2601,7 @@ namespace Barotrauma
|
||||
if (container != null)
|
||||
{
|
||||
if (!container.HasRequiredItems(this, addMessage: false)) { return false; }
|
||||
if (!container.DrawInventory) { return false; }
|
||||
if (!container.AllowAccess) { return false; }
|
||||
}
|
||||
}
|
||||
return true;
|
||||
@@ -2587,10 +2663,7 @@ namespace Barotrauma
|
||||
if (itemPriority <= 0) { continue; }
|
||||
Vector2 itemPos = (rootInventoryOwner ?? item).WorldPosition;
|
||||
Vector2 refPos = positionalReference != null ? positionalReference.WorldPosition : WorldPosition;
|
||||
float yDist = Math.Abs(refPos.Y - itemPos.Y);
|
||||
yDist = yDist > 100 ? yDist * 5 : 0;
|
||||
float dist = Math.Abs(refPos.X - itemPos.X) + yDist;
|
||||
float distanceFactor = MathHelper.Lerp(1, 0, MathUtils.InverseLerp(0, maxItemDistance, dist));
|
||||
float distanceFactor = AIObjective.GetDistanceFactor(refPos, itemPos, verticalDistanceMultiplier: 5, maxDistance: maxItemDistance, factorAtMaxDistance: 0);
|
||||
itemPriority *= distanceFactor;
|
||||
if (itemPriority > _selectedItemPriority)
|
||||
{
|
||||
@@ -2881,11 +2954,22 @@ namespace Barotrauma
|
||||
//disable aim assist when rewiring to make it harder to accidentally select items when adding wire nodes
|
||||
aimAssist = 0.0f;
|
||||
}
|
||||
|
||||
focusedItem = CanInteract ? FindItemAtPosition(mouseSimPos, aimAssist) : null;
|
||||
if (focusedItem != null && focusedItem.CampaignInteractionType != CampaignMode.InteractionType.None)
|
||||
|
||||
UpdateInteractablesInRange();
|
||||
|
||||
if (!ShowInteractionLabels) // show labels handles setting the focused item in CharacterHUD, so we can click on them boxes
|
||||
{
|
||||
FocusedCharacter = null;
|
||||
focusedItem = CanInteract ? FindClosestItem(interactablesInRange, mouseSimPos, aimAssist) : null;
|
||||
}
|
||||
|
||||
if (focusedItem != null)
|
||||
{
|
||||
if (focusedItem.CampaignInteractionType != CampaignMode.InteractionType.None ||
|
||||
/*pets' "play" interaction can interfere with interacting with items, so let's remove focus from the pet if the cursor is closer to a highlighted item*/
|
||||
FocusedCharacter is { IsPet: true } && Vector2.DistanceSquared(focusedItem.SimPosition, mouseSimPos) < Vector2.DistanceSquared(FocusedCharacter.SimPosition, mouseSimPos))
|
||||
{
|
||||
FocusedCharacter = null;
|
||||
}
|
||||
}
|
||||
findFocusedTimer = 0.05f;
|
||||
}
|
||||
@@ -3068,7 +3152,7 @@ namespace Barotrauma
|
||||
{
|
||||
if (!c.Enabled || c.AnimController.Frozen) continue;
|
||||
|
||||
c.AnimController.UpdateAnim(deltaTime);
|
||||
c.AnimController.UpdateAnimations(deltaTime);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3078,7 +3162,7 @@ namespace Barotrauma
|
||||
{
|
||||
foreach (Character c in CharacterList)
|
||||
{
|
||||
if (!(c is AICharacter) && !c.IsRemotePlayer) continue;
|
||||
if (c is not AICharacter && !c.IsRemotePlayer) { continue; }
|
||||
|
||||
if (c.IsPlayer || (c.IsBot && !c.IsDead))
|
||||
{
|
||||
@@ -3136,8 +3220,14 @@ namespace Barotrauma
|
||||
System.Diagnostics.Debug.Assert(character != null && !character.Removed);
|
||||
character.Update(deltaTime, cam);
|
||||
}
|
||||
|
||||
#if CLIENT
|
||||
UpdateSpeechBubbles(deltaTime);
|
||||
#endif
|
||||
}
|
||||
|
||||
static partial void UpdateSpeechBubbles(float deltaTime);
|
||||
|
||||
public virtual void Update(float deltaTime, Camera cam)
|
||||
{
|
||||
UpdateProjSpecific(deltaTime, cam);
|
||||
@@ -3175,8 +3265,6 @@ namespace Barotrauma
|
||||
PreviousHull = CurrentHull;
|
||||
CurrentHull = Hull.FindHull(WorldPosition, CurrentHull, useWorldCoordinates: true);
|
||||
|
||||
speechBubbleTimer = Math.Max(0.0f, speechBubbleTimer - deltaTime);
|
||||
|
||||
obstructVisionAmount = Math.Max(obstructVisionAmount - deltaTime, 0.0f);
|
||||
|
||||
if (Inventory != null)
|
||||
@@ -3335,11 +3423,14 @@ namespace Barotrauma
|
||||
else if (!tooFastToUnragdoll)
|
||||
{
|
||||
IsRagdolled = IsKeyDown(InputType.Ragdoll); //Handle this here instead of Control because we can stop being ragdolled ourselves
|
||||
if (wasRagdolled != IsRagdolled) { ragdollingLockTimer = 0.2f; }
|
||||
if (wasRagdolled != IsRagdolled && !AnimController.IsHangingWithRope)
|
||||
{
|
||||
ragdollingLockTimer = 0.2f;
|
||||
}
|
||||
}
|
||||
SetInput(InputType.Ragdoll, false, IsRagdolled);
|
||||
}
|
||||
if (!wasRagdolled && IsRagdolled)
|
||||
if (!wasRagdolled && IsRagdolled && !AnimController.IsHangingWithRope)
|
||||
{
|
||||
CheckTalents(AbilityEffectType.OnRagdoll);
|
||||
}
|
||||
@@ -3599,7 +3690,7 @@ namespace Barotrauma
|
||||
|
||||
Identifier despawnContainerId =
|
||||
IsHuman ?
|
||||
"despawncontainer".ToIdentifier() :
|
||||
Tags.DespawnContainer :
|
||||
Params.DespawnContainer;
|
||||
if (!despawnContainerId.IsEmpty)
|
||||
{
|
||||
@@ -3627,6 +3718,14 @@ namespace Barotrauma
|
||||
var itemContainer = item?.GetComponent<ItemContainer>();
|
||||
if (itemContainer == null) { return; }
|
||||
List<Item> inventoryItems = new List<Item>(Inventory.AllItemsMod);
|
||||
|
||||
//unequipping genetic materials normally destroys it in GeneticMaterial.Update, let's do that manually here
|
||||
var geneticMaterials = Inventory.FindAllItems(it => it.GetComponent<GeneticMaterial>() != null, recursive: true);
|
||||
foreach (var geneticMaterial in geneticMaterials)
|
||||
{
|
||||
geneticMaterial.ApplyStatusEffects(ActionType.OnSevered, 1.0f, this);
|
||||
}
|
||||
|
||||
foreach (Item inventoryItem in inventoryItems)
|
||||
{
|
||||
if (!itemContainer.Inventory.TryPutItem(inventoryItem, user: null, createNetworkEvent: createNetworkEvents))
|
||||
@@ -3677,13 +3776,12 @@ namespace Barotrauma
|
||||
float minRange = Math.Clamp((float)Math.Sqrt(Mass) * Visibility, 250, 1000);
|
||||
float massFactor = (float)Math.Sqrt(Mass / 20);
|
||||
float targetRange = Math.Min(minRange + massFactor * AnimController.Collider.LinearVelocity.Length() * 2 * Visibility, maxAIRange);
|
||||
targetRange *= 1.0f + GetStatValue(StatTypes.SightRangeMultiplier);
|
||||
float newRange = MathHelper.SmoothStep(aiTarget.SightRange, targetRange, deltaTime * aiTargetChangeSpeed);
|
||||
newRange *= 1.0f + GetStatValue(StatTypes.SightRangeMultiplier);
|
||||
if (!float.IsNaN(newRange))
|
||||
{
|
||||
aiTarget.SightRange = newRange;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateSoundRange(float deltaTime)
|
||||
@@ -3697,8 +3795,8 @@ namespace Barotrauma
|
||||
{
|
||||
float massFactor = (float)Math.Sqrt(Mass / 10);
|
||||
float targetRange = Math.Min(massFactor * AnimController.Collider.LinearVelocity.Length() * 2 * Noise, maxAIRange);
|
||||
targetRange *= 1.0f + GetStatValue(StatTypes.SoundRangeMultiplier);
|
||||
float newRange = MathHelper.SmoothStep(aiTarget.SoundRange, targetRange, deltaTime * aiTargetChangeSpeed);
|
||||
newRange *= 1.0f + GetStatValue(StatTypes.SoundRangeMultiplier);
|
||||
if (!float.IsNaN(newRange))
|
||||
{
|
||||
aiTarget.SoundRange = newRange;
|
||||
@@ -3975,7 +4073,9 @@ namespace Barotrauma
|
||||
GameMain.Server.SendChatMessage(message.Message, message.MessageType.Value, null, this);
|
||||
}
|
||||
#endif
|
||||
ShowSpeechBubble(2.0f, ChatMessage.MessageColor[(int)message.MessageType.Value]);
|
||||
#if CLIENT
|
||||
ShowSpeechBubble(ChatMessage.MessageColor[(int)message.MessageType.Value], message.Message);
|
||||
#endif
|
||||
sentMessages.Add(message);
|
||||
}
|
||||
|
||||
@@ -4006,13 +4106,6 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void ShowSpeechBubble(float duration, Color color)
|
||||
{
|
||||
speechBubbleTimer = Math.Max(speechBubbleTimer, duration);
|
||||
speechBubbleColor = color;
|
||||
}
|
||||
|
||||
public void SetAllDamage(float damageAmount, float bleedingDamageAmount, float burnDamageAmount)
|
||||
{
|
||||
CharacterHealth.SetAllDamage(damageAmount, bleedingDamageAmount, burnDamageAmount);
|
||||
@@ -4321,8 +4414,8 @@ namespace Barotrauma
|
||||
{
|
||||
if (affliction.Prefab.IsBuff) { continue; }
|
||||
if (Params.IsMachine && !affliction.Prefab.AffectMachines) { continue; }
|
||||
if (affliction.Prefab.AfflictionType == AfflictionPrefab.PoisonType ||
|
||||
affliction.Prefab.AfflictionType == AfflictionPrefab.ParalysisType)
|
||||
if (Params.Health.ImmunityIdentifiers.Contains(affliction.Identifier)) { continue; }
|
||||
if (affliction.Prefab.AfflictionType == AfflictionPrefab.PoisonType || affliction.Prefab.AfflictionType == AfflictionPrefab.ParalysisType)
|
||||
{
|
||||
if (!Params.Health.PoisonImmunity)
|
||||
{
|
||||
@@ -4389,7 +4482,7 @@ namespace Barotrauma
|
||||
/// Is the character knocked down regardless whether the technical state is dead, unconcious, paralyzed, or stunned.
|
||||
/// With stunning, the parameter uses an one second delay before the character is treated as knocked down. The purpose of this is to ignore minor stunning. If you don't want to to ignore any stun, use the Stun property.
|
||||
/// </summary>
|
||||
public bool IsKnockedDown => IsRagdolled || CharacterHealth.StunTimer > 1.0f || IsIncapacitated;
|
||||
public bool IsKnockedDown => (IsRagdolled && !AnimController.IsHangingWithRope) || CharacterHealth.StunTimer > 1.0f || IsIncapacitated;
|
||||
|
||||
public void SetStun(float newStun, bool allowStunDecrease = false, bool isNetworkMessage = false)
|
||||
{
|
||||
@@ -4602,6 +4695,15 @@ namespace Barotrauma
|
||||
|
||||
isDead = true;
|
||||
|
||||
// Save these resistances in the CharacterInfo object so that if they
|
||||
// are needed for respawning, they will be available (because there
|
||||
// will be no Character instance in the limbo/bardo state)
|
||||
if (info != null)
|
||||
{
|
||||
info.LastResistanceMultiplierSkillLossDeath = GetAbilityResistance(Tags.SkillLossDeathResistance);
|
||||
info.LastResistanceMultiplierSkillLossRespawn = GetAbilityResistance(Tags.SkillLossRespawnResistance);
|
||||
}
|
||||
|
||||
ApplyStatusEffects(ActionType.OnDeath, 1.0f);
|
||||
|
||||
AnimController.Frozen = false;
|
||||
@@ -4610,7 +4712,7 @@ namespace Barotrauma
|
||||
causeOfDeath, causeOfDeathAffliction?.Prefab,
|
||||
causeOfDeathAffliction?.Source, LastDamageSource);
|
||||
|
||||
if (GameAnalyticsManager.SendUserStatistics)
|
||||
if (GameAnalyticsManager.SendUserStatistics && Prefab?.ContentPackage == ContentPackageManager.VanillaCorePackage)
|
||||
{
|
||||
string causeOfDeathStr = causeOfDeathAffliction == null ?
|
||||
causeOfDeath.ToString() : causeOfDeathAffliction.Prefab.Identifier.Value.Replace(" ", "");
|
||||
@@ -5096,7 +5198,7 @@ namespace Barotrauma
|
||||
|
||||
public bool IsImmuneToPressure => !NeedsAir || HasAbilityFlag(AbilityFlags.ImmuneToPressure);
|
||||
|
||||
#region Talents
|
||||
#region Talents
|
||||
private readonly List<CharacterTalent> characterTalents = new List<CharacterTalent>();
|
||||
|
||||
public IReadOnlyCollection<CharacterTalent> CharacterTalents => characterTalents;
|
||||
@@ -5214,7 +5316,7 @@ namespace Barotrauma
|
||||
|
||||
partial void OnTalentGiven(TalentPrefab talentPrefab);
|
||||
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
private readonly HashSet<Hull> sameRoomHulls = new();
|
||||
|
||||
@@ -5426,6 +5528,24 @@ namespace Barotrauma
|
||||
|
||||
private readonly Dictionary<TalentResistanceIdentifier, float> abilityResistances = new();
|
||||
|
||||
public float GetAbilityResistance(Identifier resistanceId)
|
||||
{
|
||||
float resistance = 0f;
|
||||
bool hadResistance = false;
|
||||
|
||||
foreach (var (key, value) in abilityResistances)
|
||||
{
|
||||
if (key.ResistanceIdentifier == resistanceId)
|
||||
{
|
||||
resistance += value;
|
||||
hadResistance = true;
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: Resistance is handled as a multiplier here, so 1.0 == 0% resistance
|
||||
return hadResistance ? resistance : 1f;
|
||||
}
|
||||
|
||||
public float GetAbilityResistance(AfflictionPrefab affliction)
|
||||
{
|
||||
float resistance = 0f;
|
||||
@@ -5441,6 +5561,7 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: Resistance is handled as a multiplier here, so 1.0 == 0% resistance
|
||||
return hadResistance ? resistance : 1f;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user