Unstable 1.1.14.0
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user