Unstable 1.1.14.0

This commit is contained in:
Markus Isberg
2023-10-02 16:43:54 +03:00
parent 94f5a93a0c
commit cf8f0de659
606 changed files with 21906 additions and 11456 deletions
@@ -65,6 +65,13 @@ namespace Barotrauma
}
UpdateLimbLightSource(limb);
}
foreach (var item in HeldItems)
{
if (item.body != null)
{
item.body.Enabled = enabled;
}
}
AnimController.Collider.Enabled = value;
}
}
@@ -335,7 +342,7 @@ namespace Barotrauma
public bool IsInstigator => CombatAction != null && CombatAction.IsInstigator;
public CombatAction CombatAction;
public AnimController AnimController;
public readonly AnimController AnimController;
private Vector2 cursorPosition;
@@ -386,6 +393,8 @@ namespace Barotrauma
public bool IsMachine => Params.IsMachine;
public bool IsHusk => Params.Husk;
public bool IsDisguisedAsHusk => CharacterHealth.GetAfflictionStrengthByType("disguiseashusk".ToIdentifier()) > 0;
public bool IsHuskInfected => CharacterHealth.GetActiveAfflictionTags().Contains("huskinfected".ToIdentifier());
public bool IsMale => info?.IsMale ?? false;
@@ -781,7 +790,7 @@ namespace Barotrauma
get
{
if (IsUnconscious) { return true; }
return CharacterHealth.GetAllAfflictions().Any(a => a.Prefab.AfflictionType == AfflictionPrefab.ParalysisType && a.Strength >= a.Prefab.MaxStrength);
return CharacterHealth.IsParalyzed;
}
}
@@ -792,7 +801,7 @@ namespace Barotrauma
public bool IsArrested
{
get { return IsHuman && HasEquippedItem("handlocker"); }
get { return IsHuman && HasEquippedItem(Tags.HandLockerItem); }
}
public bool IsPet
@@ -852,6 +861,7 @@ namespace Barotrauma
public bool IsLatched => AIController is EnemyAIController enemyAI && enemyAI.LatchOntoAI != null && enemyAI.LatchOntoAI.IsAttached;
public float EmpVulnerability => Params.Health.EmpVulnerability;
public float PoisonVulnerability => Params.Health.PoisonVulnerability;
public bool IsFlipped => AnimController.IsFlipped;
public float Bloodloss
{
@@ -865,7 +875,7 @@ namespace Barotrauma
public float Bleeding
{
get { return CharacterHealth.GetAfflictionStrength(AfflictionPrefab.BleedingType, true); }
get { return CharacterHealth.GetAfflictionStrengthByType(AfflictionPrefab.BleedingType, true); }
}
private bool speechImpedimentSet;
@@ -936,6 +946,8 @@ namespace Barotrauma
{
GameMain.GameSession?.CrewManager?.AutoHideCrewList();
}
_selectedItem?.GetComponent<CircuitBox>()?.OnViewUpdateProjSpecific();
}
#endif
if (prevSelectedItem != null && (_selectedItem == null || _selectedItem != prevSelectedItem) && itemSelectedTime > 0)
@@ -1073,8 +1085,17 @@ namespace Barotrauma
public bool IsLowInOxygen => CharacterHealth.OxygenAmount < 100;
/// <summary>
/// Godmoded characters cannot receive any afflictions whatsoever
/// </summary>
public bool GodMode = false;
public bool Unkillable
{
get { return CharacterHealth.Unkillable; }
set { CharacterHealth.Unkillable = value; }
}
public CampaignMode.InteractionType CampaignInteractionType;
public Identifier MerchantIdentifier;
@@ -1308,9 +1329,9 @@ namespace Barotrauma
break;
}
}
if (Params.VariantFile != null)
if (Params.VariantFile != null && Params.MainElement is ContentXElement paramsMainElement)
{
var overrideElement = Params.VariantFile.Root.FromPackage(Params.MainElement.ContentPackage);
var overrideElement = Params.VariantFile.Root.FromPackage(paramsMainElement.ContentPackage);
// Only override if the override file contains matching elements
if (overrideElement.GetChildElement("inventory") != null)
{
@@ -1484,7 +1505,7 @@ namespace Barotrauma
var head = AnimController.GetLimb(LimbType.Head);
if (head == null) { return; }
// Note that if there are any other wearables on the head, they are removed here.
head.OtherWearables.ForEach(w => w.Sprite.Remove());
head.OtherWearables.ForEach(w => w.Sprite?.Remove());
head.OtherWearables.Clear();
//if the element has not been set at this point, the character has no hair and the index should be zero (= no hair)
@@ -1664,17 +1685,31 @@ namespace Barotrauma
info.Job?.GiveJobItems(this, spawnPoint);
}
public void GiveIdCardTags(WayPoint spawnPoint, bool createNetworkEvent = false)
public void GiveIdCardTags(WayPoint spawnPoint, bool requireSpawnPointTagsNotGiven = true, bool createNetworkEvent = false)
{
if (info?.Job == null || spawnPoint == null) { return; }
GiveIdCardTags(spawnPoint.ToEnumerable(), requireSpawnPointTagsNotGiven, createNetworkEvent);
}
public void GiveIdCardTags(IEnumerable<WayPoint> spawnPoints, bool requireSpawnPointTagsNotGiven = true, bool createNetworkEvent = false)
{
if (info?.Job == null || spawnPoints == null) { return; }
foreach (Item item in Inventory.AllItems)
{
if (item?.GetComponent<IdCard>() == null) { continue; }
foreach (string s in spawnPoint.IdCardTags)
if (item?.GetComponent<IdCard>() is not IdCard idCard) { continue; }
if (requireSpawnPointTagsNotGiven)
{
item.AddTag(s);
if (idCard.SpawnPointTagsGiven) { continue; }
}
foreach (var spawnPoint in spawnPoints)
{
foreach (string s in spawnPoint.IdCardTags)
{
item.AddTag(s);
}
}
idCard.SpawnPointTagsGiven = true;
if (createNetworkEvent && GameMain.NetworkMember is { IsServer: true })
{
GameMain.NetworkMember.CreateEntityEvent(item, new Item.ChangePropertyEventData(item.SerializableProperties[nameof(item.Tags).ToIdentifier()], item));
@@ -1983,14 +2018,21 @@ namespace Barotrauma
if (AnimController is HumanoidAnimController humanAnimController)
{
humanAnimController.Crouching = humanAnimController.ForceSelectAnimationType == AnimationType.Crouch || IsKeyDown(InputType.Crouch);
humanAnimController.Crouching =
humanAnimController.ForceSelectAnimationType == AnimationType.Crouch ||
IsKeyDown(InputType.Crouch);
if (Screen.Selected is not { IsEditor: true })
{
humanAnimController.ForceSelectAnimationType = AnimationType.NotDefined;
}
}
if (!aiControlled &&
!AnimController.IsUsingItem &&
AnimController.Anim != AnimController.Animation.CPR &&
(GameMain.NetworkMember == null || !GameMain.NetworkMember.IsClient || Controlled == this) &&
(AnimController.OnGround || IsClimbing) && !AnimController.InWater)
((!IsClimbing && AnimController.OnGround) || (IsClimbing && IsKeyDown(InputType.Aim))) &&
!AnimController.InWater)
{
if (dontFollowCursor)
{
@@ -2187,14 +2229,14 @@ namespace Barotrauma
{
if (!item.RequireAimToUse || IsKeyDown(InputType.Aim))
{
item.Use(deltaTime, this);
item.Use(deltaTime, user: this);
}
}
if (IsKeyDown(InputType.Shoot) && item.IsShootable)
{
if (!item.RequireAimToUse || IsKeyDown(InputType.Aim))
{
item.Use(deltaTime, this);
item.Use(deltaTime, user: this);
}
#if CLIENT
else if (item.RequireAimToUse && !IsKeyDown(InputType.Aim))
@@ -2214,7 +2256,7 @@ namespace Barotrauma
{
if (!SelectedCharacter.CanBeSelected ||
(Vector2.DistanceSquared(SelectedCharacter.WorldPosition, WorldPosition) > MaxDragDistance * MaxDragDistance &&
SelectedCharacter.GetDistanceToClosestLimb(SimPosition) > ConvertUnits.ToSimUnits(MaxDragDistance)))
SelectedCharacter.GetDistanceToClosestLimb(GetRelativeSimPosition(selectedCharacter, WorldPosition)) > ConvertUnits.ToSimUnits(MaxDragDistance)))
{
DeselectCharacter();
}
@@ -2247,26 +2289,58 @@ namespace Barotrauma
};
}
public bool CanSeeCharacter(Character target)
private Limb GetSeeingLimb()
{
return AnimController.GetLimb(LimbType.Head) ?? AnimController.GetLimb(LimbType.Torso) ?? AnimController.MainLimb;
}
public bool CanSeeTarget(ISpatialEntity target, ISpatialEntity seeingEntity = null, bool checkFacing = false)
{
seeingEntity ??= AnimController.SimplePhysicsEnabled ? this : GetSeeingLimb();
if (target is Character targetCharacter)
{
return IsCharacterVisible(targetCharacter, seeingEntity, checkFacing);
}
else
{
return CheckVisibility(target, seeingEntity, checkFacing);
}
}
public static bool IsTargetVisible(ISpatialEntity target, ISpatialEntity seeingEntity, bool checkFacing = false)
{
if (seeingEntity is Character seeingCharacter)
{
return seeingCharacter.CanSeeTarget(target, checkFacing: checkFacing);
}
if (target is Character targetCharacter)
{
return IsCharacterVisible(targetCharacter, seeingEntity, checkFacing);
}
else
{
return CheckVisibility(target, seeingEntity, checkFacing);
}
}
private static bool IsCharacterVisible(Character target, ISpatialEntity seeingEntity, bool checkFacing = false)
{
System.Diagnostics.Debug.Assert(target != null);
if (target == null) { return false; }
if (target.Removed) { return false; }
Limb seeingLimb = GetSeeingLimb();
if (CanSeeTarget(target, seeingLimb)) { return true; }
if (target == null || target.Removed) { return false; }
if (CheckVisibility(target, seeingEntity, checkFacing)) { return true; }
if (!target.AnimController.SimplePhysicsEnabled)
{
//find the limbs that are furthest from the target's position (from the viewer's point of view)
Limb leftExtremity = null, rightExtremity = null;
float leftMostDot = 0.0f, rightMostDot = 0.0f;
Vector2 dir = target.WorldPosition - WorldPosition;
Vector2 dir = target.WorldPosition - seeingEntity.WorldPosition;
Vector2 leftDir = new Vector2(dir.Y, -dir.X);
Vector2 rightDir = new Vector2(-dir.Y, dir.X);
foreach (Limb limb in target.AnimController.Limbs)
{
if (limb.IsSevered || limb == target.AnimController.MainLimb) { continue; }
if (limb.Hidden) { continue; }
Vector2 limbDir = limb.WorldPosition - WorldPosition;
Vector2 limbDir = limb.WorldPosition - seeingEntity.WorldPosition;
float leftDot = Vector2.Dot(limbDir, leftDir);
if (leftDot > leftMostDot)
{
@@ -2282,42 +2356,39 @@ namespace Barotrauma
continue;
}
}
if (leftExtremity != null && CanSeeTarget(leftExtremity, seeingLimb)) { return true; }
if (rightExtremity != null && CanSeeTarget(rightExtremity, seeingLimb)) { return true; }
if (leftExtremity != null && CheckVisibility(leftExtremity, seeingEntity, checkFacing)) { return true; }
if (rightExtremity != null && CheckVisibility(rightExtremity, seeingEntity, checkFacing)) { return true; }
}
return false;
}
private Limb GetSeeingLimb()
{
return AnimController.GetLimb(LimbType.Head) ?? AnimController.GetLimb(LimbType.Torso) ?? AnimController.MainLimb;
}
public bool CanSeeTarget(ISpatialEntity target, ISpatialEntity seeingEntity = null)
private static bool CheckVisibility(ISpatialEntity target, ISpatialEntity seeingEntity, bool checkFacing = false)
{
System.Diagnostics.Debug.Assert(target != null);
if (target == null) { return false; }
seeingEntity ??= AnimController.SimplePhysicsEnabled ? this : GetSeeingLimb() as ISpatialEntity;
if (seeingEntity == null) { return false; }
ISpatialEntity sourceEntity = seeingEntity ;
// TODO: Could we just use the method below? If not, let's refactor it so that we can.
Vector2 diff = ConvertUnits.ToSimUnits(target.WorldPosition - sourceEntity.WorldPosition);
Vector2 diff = ConvertUnits.ToSimUnits(target.WorldPosition - seeingEntity.WorldPosition);
if (checkFacing && seeingEntity is Character seeingCharacter)
{
if (Math.Sign(diff.X) != seeingCharacter.AnimController.Dir) { return false; }
}
Body closestBody;
//both inside the same sub (or both outside)
//OR the we're inside, the other character outside
if (target.Submarine == Submarine || target.Submarine == null)
if (target.Submarine == seeingEntity.Submarine || target.Submarine == null)
{
closestBody = Submarine.CheckVisibility(sourceEntity.SimPosition, sourceEntity.SimPosition + diff);
closestBody = Submarine.CheckVisibility(seeingEntity.SimPosition, seeingEntity.SimPosition + diff);
}
//we're outside, the other character inside
else if (Submarine == null)
else if (seeingEntity.Submarine == null)
{
closestBody = Submarine.CheckVisibility(target.SimPosition, target.SimPosition - diff);
}
//both inside different subs
else
{
closestBody = Submarine.CheckVisibility(sourceEntity.SimPosition, sourceEntity.SimPosition + diff);
closestBody = Submarine.CheckVisibility(seeingEntity.SimPosition, seeingEntity.SimPosition + diff);
if (!IsBlocking(closestBody))
{
closestBody = Submarine.CheckVisibility(target.SimPosition, target.SimPosition - diff);
@@ -2370,9 +2441,6 @@ namespace Barotrauma
return false;
}
public bool HasEquippedItem(string tagOrIdentifier, bool allowBroken = true, InvSlotType? slotType = null)
=> HasEquippedItem(tagOrIdentifier.ToIdentifier(), allowBroken, slotType);
public bool HasEquippedItem(Identifier tagOrIdentifier, bool allowBroken = true, InvSlotType? slotType = null)
{
if (Inventory == null) { return false; }
@@ -2394,7 +2462,7 @@ namespace Barotrauma
return false;
}
public Item GetEquippedItem(string tagOrIdentifier = null, InvSlotType? slotType = null)
public Item GetEquippedItem(Identifier? tagOrIdentifier = null, InvSlotType? slotType = null)
{
if (Inventory == null) { return null; }
for (int i = 0; i < Inventory.Capacity; i++)
@@ -2409,7 +2477,10 @@ namespace Barotrauma
}
var item = Inventory.GetItemAt(i);
if (item == null) { continue; }
if (tagOrIdentifier == null || item.Prefab.Identifier == tagOrIdentifier || item.HasTag(tagOrIdentifier)) { return item; }
if (tagOrIdentifier == null || tagOrIdentifier.Value.IsEmpty || item.Prefab.Identifier == tagOrIdentifier || item.HasTag(tagOrIdentifier.Value))
{
return item;
}
}
return null;
}
@@ -2537,7 +2608,7 @@ namespace Barotrauma
}
}
return !checkVisibility || CanSeeCharacter(c);
return !checkVisibility || CanSeeTarget(c);
}
public bool CanInteractWith(Item item, bool checkLinked = true)
@@ -2587,7 +2658,10 @@ namespace Barotrauma
{
foreach (MapEntity linked in item.linkedTo)
{
if (linked is Item linkedItem)
if (linked is Item linkedItem &&
//if the linked item is inside this container (a modder or sub builder doing smth really weird?)
//don't check it here because it'd lead to an infinite loop
linkedItem.ParentInventory?.Owner != item)
{
if (CanInteractWith(linkedItem, out float distToLinked, checkLinked: false))
{
@@ -2675,10 +2749,18 @@ namespace Barotrauma
if (SelectedSecondaryItem != null && !item.IsSecondaryItem)
{
//don't allow selecting another Controller if it'd try to turn the character in the opposite direction
//(e.g. periscope that's facing the wrong way while sitting in a chair)
if (item.GetComponent<Controller>() is { } controller && controller.Direction != 0 && controller.Direction != AnimController.Direction) { return false; }
float threshold = ConvertUnits.ToSimUnits(cursorFollowMargin);
if (AnimController.Direction == Direction.Left && SimPosition.X + threshold < itemPosition.X) { return false; }
if (AnimController.Direction == Direction.Right && SimPosition.X - threshold > itemPosition.X) { return false; }
//if a Controller that controls the character's pose is selected,
//don't allow selecting items that are behind the character's back
if (SelectedSecondaryItem.GetComponent<Controller>() is { ControlCharacterPose: true } selectedController)
{
float threshold = ConvertUnits.ToSimUnits(cursorFollowMargin);
if (AnimController.Direction == Direction.Left && SimPosition.X + threshold < itemPosition.X) { return false; }
if (AnimController.Direction == Direction.Right && SimPosition.X - threshold > itemPosition.X) { return false; }
}
}
if (!item.Prefab.InteractThroughWalls && Screen.Selected != GameMain.SubEditorScreen && !insideTrigger)
@@ -2703,7 +2785,7 @@ namespace Barotrauma
this.onCustomInteract = onCustomInteract;
CustomInteractHUDText = hudText;
}
public void SelectCharacter(Character character)
{
if (character == null || character == this) { return; }
@@ -2754,7 +2836,7 @@ namespace Barotrauma
if (!PlayerInput.PrimaryMouseButtonHeld() || Barotrauma.Inventory.DraggingItemToWorld)
{
FocusedCharacter = CanInteract || CanEat ? FindCharacterAtPosition(mouseSimPos) : null;
if (FocusedCharacter != null && !CanSeeCharacter(FocusedCharacter)) { FocusedCharacter = null; }
if (FocusedCharacter != null && !CanSeeTarget(FocusedCharacter)) { FocusedCharacter = null; }
float aimAssist = GameSettings.CurrentConfig.AimAssistAmount * (AnimController.InWater ? 1.5f : 1.0f);
if (HeldItems.Any(it => it?.GetComponent<Wire>()?.IsActive ?? false))
{
@@ -2867,7 +2949,7 @@ namespace Barotrauma
}
#endif
}
else
else if (!IsClimbing)
{
#if CLIENT
if (Controlled == this)
@@ -2915,9 +2997,9 @@ namespace Barotrauma
CharacterHealth.OpenHealthWindow = null;
#endif
}
else if (IsKeyHit(InputType.Health) && (SelectedItem != null || SelectedSecondaryItem != null))
else if (IsKeyHit(InputType.Health) && SelectedItem != null)
{
SelectedItem = SelectedSecondaryItem = null;
SelectedItem = null;
}
else if (focusedItem != null)
{
@@ -3107,6 +3189,14 @@ namespace Barotrauma
//implode if not protected from pressure, and either outside or in a high-pressure hull
if (!IsProtectedFromPressure && (AnimController.CurrentHull == null || AnimController.CurrentHull.LethalPressure >= 80.0f))
{
if (PressureTimer > CharacterHealth.PressureKillDelay * 0.1f)
{
//after a brief delay, start doing increasing amounts of organ damage
CharacterHealth.ApplyAffliction(
targetLimb: AnimController.MainLimb,
new Affliction(AfflictionPrefab.OrganDamage, PressureTimer / 10.0f * deltaTime));
}
if (CharacterHealth.PressureKillDelay <= 0.0f)
{
PressureTimer = 100.0f;
@@ -3176,47 +3266,48 @@ namespace Barotrauma
UpdateAIChatMessages(deltaTime);
if (GameMain.NetworkMember?.ServerSettings?.AllowRagdollButton ?? true)
bool wasRagdolled = IsRagdolled;
if (IsForceRagdolled)
{
bool wasRagdolled = IsRagdolled;
if (IsForceRagdolled)
IsRagdolled = IsForceRagdolled;
}
else if (this != Controlled)
{
wasRagdolled = IsRagdolled;
IsRagdolled = IsKeyDown(InputType.Ragdoll);
if (IsRagdolled && IsBot && GameMain.NetworkMember is not { IsClient: true })
{
IsRagdolled = IsForceRagdolled;
}
else if (this != Controlled)
{
wasRagdolled = IsRagdolled;
IsRagdolled = IsKeyDown(InputType.Ragdoll);
}
else
{
bool tooFastToUnragdoll = bodyMovingTooFast(AnimController.Collider) || bodyMovingTooFast(AnimController.MainLimb.body);
bool bodyMovingTooFast(PhysicsBody body)
{
return
body.LinearVelocity.LengthSquared() > 8.0f * 8.0f ||
//falling down counts as going too fast
(!InWater && body.LinearVelocity.Y < -5.0f);
}
if (ragdollingLockTimer > 0.0f)
{
ragdollingLockTimer -= deltaTime;
}
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 (IsRagdolled)
{
SetInput(InputType.Ragdoll, false, true);
}
}
if (!wasRagdolled && IsRagdolled)
{
CheckTalents(AbilityEffectType.OnRagdoll);
ClearInput(InputType.Ragdoll);
}
}
else
{
bool tooFastToUnragdoll = bodyMovingTooFast(AnimController.Collider) || bodyMovingTooFast(AnimController.MainLimb.body);
bool bodyMovingTooFast(PhysicsBody body)
{
return
body.LinearVelocity.LengthSquared() > 8.0f * 8.0f ||
//falling down counts as going too fast
(!InWater && body.LinearVelocity.Y < -5.0f);
}
if (ragdollingLockTimer > 0.0f)
{
ragdollingLockTimer -= deltaTime;
}
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 (IsRagdolled)
{
SetInput(InputType.Ragdoll, false, true);
}
}
if (!wasRagdolled && IsRagdolled)
{
CheckTalents(AbilityEffectType.OnRagdoll);
}
lowPassMultiplier = MathHelper.Lerp(lowPassMultiplier, 1.0f, 0.1f);
@@ -3419,7 +3510,7 @@ namespace Barotrauma
}
private float despawnTimer;
private void UpdateDespawn(float deltaTime, bool ignoreThresholds = false, bool createNetworkEvents = true)
private void UpdateDespawn(float deltaTime, bool createNetworkEvents = true)
{
if (!EnableDespawn) { return; }
@@ -3430,7 +3521,7 @@ namespace Barotrauma
int subCorpseCount = 0;
if (Submarine != null && !ignoreThresholds)
if (Submarine != null)
{
subCorpseCount = CharacterList.Count(c => c.IsDead && c.Submarine == Submarine);
if (subCorpseCount < GameSettings.CurrentConfig.CorpsesPerSubDespawnThreshold) { return; }
@@ -3464,6 +3555,11 @@ namespace Barotrauma
despawnTimer += deltaTime * despawnPriority;
if (despawnTimer < GameSettings.CurrentConfig.CorpseDespawnDelay) { return; }
Despawn();
}
private void Despawn(bool createNetworkEvents = true)
{
Identifier despawnContainerId =
IsHuman ?
"despawncontainer".ToIdentifier() :
@@ -3514,8 +3610,7 @@ namespace Barotrauma
public void DespawnNow(bool createNetworkEvents = true)
{
despawnTimer = GameSettings.CurrentConfig.CorpseDespawnDelay;
UpdateDespawn(1.0f, ignoreThresholds: true, createNetworkEvents: createNetworkEvents);
Despawn(createNetworkEvents);
//update twice: first to spawn the duffel bag and move the items into it, then to remove the character
for (int i = 0; i < 2; i++)
{
@@ -4259,7 +4354,7 @@ namespace Barotrauma
if (Screen.Selected != GameMain.GameScreen) { return; }
if (newStun > 0 && Params.Health.StunImmunity)
{
if (EmpVulnerability <= 0 || CharacterHealth.GetAfflictionStrength(AfflictionPrefab.EMPType, allowLimbAfflictions: false) <= 0)
if (EmpVulnerability <= 0 || CharacterHealth.GetAfflictionStrengthByType(AfflictionPrefab.EMPType, allowLimbAfflictions: false) <= 0)
{
return;
}
@@ -4323,8 +4418,7 @@ namespace Barotrauma
if (limb.IsSevered) { continue; }
if (limb.type == limbType)
{
statusEffect.sourceBody = limb.body;
statusEffect.Apply(actionType, deltaTime, this, limb);
ApplyToLimb(actionType, deltaTime, statusEffect, this, limb);
}
}
}
@@ -4334,8 +4428,7 @@ namespace Barotrauma
Limb limb = AnimController.GetLimb(limbType);
if (limb != null)
{
statusEffect.sourceBody = limb.body;
statusEffect.Apply(actionType, deltaTime, this, limb);
ApplyToLimb(actionType, deltaTime, statusEffect, this, limb);
}
}
else if (statusEffect.HasTargetType(StatusEffect.TargetType.LastLimb))
@@ -4344,12 +4437,20 @@ namespace Barotrauma
Limb limb = AnimController.Limbs.LastOrDefault(l => l.type == limbType && !l.IsSevered && !l.Hidden);
if (limb != null)
{
statusEffect.sourceBody = limb.body;
statusEffect.Apply(actionType, deltaTime, this, limb);
ApplyToLimb(actionType, deltaTime, statusEffect, this, limb);
}
}
}
}
else if (statusEffect.HasTargetType(StatusEffect.TargetType.AllLimbs))
{
// Target all limbs
foreach (var limb in AnimController.Limbs)
{
if (limb.IsSevered) { continue; }
ApplyToLimb(actionType, deltaTime, statusEffect, character: this, limb);
}
}
if (statusEffect.HasTargetType(StatusEffect.TargetType.This) || statusEffect.HasTargetType(StatusEffect.TargetType.Character))
{
statusEffect.Apply(actionType, deltaTime, this, this);
@@ -4373,6 +4474,12 @@ namespace Barotrauma
{
CharacterHealth.ApplyAfflictionStatusEffects(actionType);
}
static void ApplyToLimb(ActionType actionType, float deltaTime, StatusEffect statusEffect, Character character, Limb limb)
{
statusEffect.sourceBody = limb.body;
statusEffect.Apply(actionType, deltaTime, entity: character, target: limb);
}
}
private void Implode(bool isNetworkMessage = false)
@@ -4433,7 +4540,7 @@ namespace Barotrauma
public void Kill(CauseOfDeathType causeOfDeath, Affliction causeOfDeathAffliction, bool isNetworkMessage = false, bool log = true)
{
if (IsDead || CharacterHealth.Unkillable || GodMode) { return; }
if (IsDead || CharacterHealth.Unkillable || GodMode || Removed) { return; }
HealthUpdateInterval = 0.0f;
@@ -4533,20 +4640,21 @@ namespace Barotrauma
SelectedCharacter = null;
AnimController.ResetPullJoints();
foreach (var joint in AnimController.LimbJoints)
if (AnimController.LimbJoints != null)
{
if (joint.revoluteJoint != null)
foreach (var joint in AnimController.LimbJoints)
{
joint.revoluteJoint.MotorEnabled = false;
if (joint.revoluteJoint != null)
{
joint.revoluteJoint.MotorEnabled = false;
}
}
}
GameMain.GameSession?.KillCharacter(this);
}
partial void KillProjSpecific(CauseOfDeathType causeOfDeath, Affliction causeOfDeathAffliction, bool log);
public void Revive(bool removeAllAfflictions = true)
public void Revive(bool removeAfflictions = true)
{
if (Removed)
{
@@ -4557,20 +4665,21 @@ namespace Barotrauma
aiTarget?.Remove();
aiTarget = new AITarget(this);
if (removeAllAfflictions)
if (removeAfflictions)
{
CharacterHealth.RemoveAllAfflictions();
SetAllDamage(0.0f, 0.0f, 0.0f);
Bloodloss = 0.0f;
SetStun(0.0f, true);
}
else
{
CharacterHealth.RemoveNegativeAfflictions();
}
SetAllDamage(0.0f, 0.0f, 0.0f);
Oxygen = 100.0f;
Bloodloss = 0.0f;
SetStun(0.0f, true);
isDead = false;
if (info != null)
{
info.CauseOfDeath = null;
}
foreach (LimbJoint joint in AnimController.LimbJoints)
{
var revoluteJoint = joint.revoluteJoint;
@@ -4594,10 +4703,7 @@ namespace Barotrauma
limb.IsSevered = false;
}
if (GameMain.GameSession != null)
{
GameMain.GameSession.ReviveCharacter(this);
}
GameMain.GameSession?.ReviveCharacter(this);
}
public override void Remove()
@@ -4712,7 +4818,7 @@ namespace Barotrauma
{
SpawnInventoryItemsRecursive(inventory, itemData, new List<Item>());
}
private void SpawnInventoryItemsRecursive(Inventory inventory, ContentXElement element, List<Item> extraDuffelBags)
{
foreach (var itemElement in element.Elements())
@@ -4737,21 +4843,6 @@ namespace Barotrauma
continue;
}
//make sure there's no other item in the slot
//this should not happen normally, but can occur if the character is accidentally given new job items while also loading previous items in the campaign
for (int i = 0; i < inventory.Capacity; i++)
{
if (slotIndices.Contains(i))
{
var existingItem = inventory.GetItemAt(i);
if (existingItem != null && existingItem != newItem && (((MapEntity)existingItem).Prefab != ((MapEntity)newItem).Prefab || existingItem.Prefab.MaxStackSize == 1))
{
DebugConsole.ThrowError($"Error while loading character inventory data. The slot {i} was already occupied by the item \"{existingItem.Name} ({existingItem.ID})\" when loading the item \"{newItem.Name} ({newItem.ID})\"");
existingItem.Drop(null, createNetworkEvent: false);
}
}
}
bool canBePutInOriginalInventory = true;
if (slotIndices[0] >= inventory.Capacity)
{
@@ -4833,6 +4924,13 @@ namespace Barotrauma
}
}
#if SERVER
foreach (var circuitBox in newItem.GetComponents<CircuitBox>())
{
circuitBox.MarkServerRequiredInitialization();
}
#endif
int itemContainerIndex = 0;
var itemContainers = newItem.GetComponents<ItemContainer>().ToList();
foreach (var childInvElement in itemElement.Elements())
@@ -4921,41 +5019,7 @@ namespace Barotrauma
return visibleHulls;
}
public Vector2 GetRelativeSimPosition(ISpatialEntity target, Vector2? worldPos = null) => GetRelativeSimPosition(this, target, worldPos);
public static Vector2 GetRelativeSimPosition(ISpatialEntity from, ISpatialEntity to, Vector2? worldPos = null)
{
Vector2 targetPos = to.SimPosition;
if (worldPos.HasValue)
{
Vector2 wp = worldPos.Value;
if (to.Submarine != null)
{
wp -= to.Submarine.Position;
}
targetPos = ConvertUnits.ToSimUnits(wp);
}
if (from.Submarine == null && to.Submarine != null)
{
// outside and targeting inside
targetPos += to.Submarine.SimPosition;
}
else if (from.Submarine != null && to.Submarine == null)
{
// inside and targeting outside
targetPos -= from.Submarine.SimPosition;
}
else if (from.Submarine != to.Submarine)
{
if (from.Submarine != null && to.Submarine != null)
{
// both inside, but in different subs
Vector2 diff = from.Submarine.SimPosition - to.Submarine.SimPosition;
targetPos -= diff;
}
}
return targetPos;
}
public Vector2 GetRelativeSimPosition(ISpatialEntity target, Vector2? worldPos = null) => Submarine.GetRelativeSimPosition(this, target, worldPos);
public bool IsCaptain => HasJob("captain");
public bool IsEngineer => HasJob("engineer");
@@ -4966,6 +5030,8 @@ namespace Barotrauma
public bool IsWatchman => HasJob("watchman");
public bool IsVip => HasJob("prisoner");
public bool IsPrisoner => HasJob("prisoner");
public bool IsKiller => HasJob("killer");
public Color? UniqueNameColor { get; set; } = null;
public bool HasJob(string identifier) => Info?.Job?.Prefab.Identifier == identifier;
@@ -5052,6 +5118,7 @@ namespace Barotrauma
public bool HasTalent(Identifier identifier)
{
if (info == null) { return false; }
return info.UnlockedTalents.Contains(identifier);
}