(f2e516dfe) v0.9.3.2
This commit is contained in:
@@ -387,14 +387,17 @@ namespace Barotrauma
|
||||
|
||||
private void UpdateIdle(float deltaTime)
|
||||
{
|
||||
if (Character.Submarine == null && SimPosition.Y < ConvertUnits.ToSimUnits(Character.CharacterHealth.CrushDepth * 0.75f))
|
||||
if (Character.Submarine == null &&
|
||||
SimPosition.Y < ConvertUnits.ToSimUnits(Character.CharacterHealth.CrushDepth * 0.75f))
|
||||
{
|
||||
//steer straight up if very deep
|
||||
steeringManager.SteeringManual(deltaTime, Vector2.UnitY);
|
||||
return;
|
||||
}
|
||||
|
||||
if (wallTarget != null) return;
|
||||
SteerInsideLevel(deltaTime);
|
||||
|
||||
if (wallTarget != null) { return; }
|
||||
|
||||
if (SelectedAiTarget != null)
|
||||
{
|
||||
@@ -451,6 +454,10 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SteerInsideLevel(deltaTime);
|
||||
}
|
||||
if (escapePoint != Vector2.Zero && Vector2.DistanceSquared(Character.SimPosition, escapePoint) > 1)
|
||||
{
|
||||
SteeringManager.SteeringSeek(escapePoint);
|
||||
@@ -1396,6 +1403,30 @@ namespace Barotrauma
|
||||
AttackingLimb = null;
|
||||
}
|
||||
|
||||
private void SteerInsideLevel(float deltaTime)
|
||||
{
|
||||
if (Level.Loaded == null) { return; }
|
||||
|
||||
Vector2 levelSimSize = new Vector2(
|
||||
ConvertUnits.ToSimUnits(Level.Loaded.Size.X),
|
||||
ConvertUnits.ToSimUnits(Level.Loaded.Size.Y));
|
||||
|
||||
float margin = 10.0f;
|
||||
|
||||
if (SimPosition.Y < 0.0f)
|
||||
{
|
||||
steeringManager.SteeringManual(deltaTime, Vector2.UnitY * MathUtils.InverseLerp(0.0f, -margin, SimPosition.Y));
|
||||
}
|
||||
if (SimPosition.X < 0.0f)
|
||||
{
|
||||
steeringManager.SteeringManual(deltaTime, Vector2.UnitX * MathUtils.InverseLerp(0.0f, -margin, SimPosition.X));
|
||||
}
|
||||
if (SimPosition.X > levelSimSize.X)
|
||||
{
|
||||
steeringManager.SteeringManual(deltaTime, Vector2.UnitX * MathUtils.InverseLerp(levelSimSize.X, levelSimSize.X + margin, SimPosition.X));
|
||||
}
|
||||
}
|
||||
|
||||
private int GetMinimumPassableHoleCount()
|
||||
{
|
||||
return (int)Math.Ceiling(ConvertUnits.ToDisplayUnits(colliderSize) / Structure.WallSectionSize);
|
||||
|
||||
@@ -81,7 +81,7 @@ namespace Barotrauma
|
||||
|
||||
public override void Update(float deltaTime)
|
||||
{
|
||||
if (DisableCrewAI || Character.IsUnconscious) return;
|
||||
if (DisableCrewAI || Character.IsUnconscious || Character.Removed) { return; }
|
||||
|
||||
float maxDistanceToSub = 3000;
|
||||
if (Character.Submarine != null || SelectedAiTarget?.Entity?.Submarine != null &&
|
||||
|
||||
@@ -312,8 +312,10 @@ namespace Barotrauma
|
||||
Vector2 colliderBottom = character.AnimController.GetColliderBottom();
|
||||
Vector2 colliderSize = collider.GetSize();
|
||||
Vector2 velocity = collider.LinearVelocity;
|
||||
// If the character is smaller than this, it fails to use the waypoint nodes, because they are always too high.
|
||||
float minHeight = 1;
|
||||
// Cannot use the head position, because not all characters have head or it can be below the total height of the character
|
||||
float characterHeight = colliderSize.Y + character.AnimController.ColliderHeightFromFloor;
|
||||
float characterHeight = Math.Max(colliderSize.Y + character.AnimController.ColliderHeightFromFloor, minHeight);
|
||||
float horizontalDistance = Math.Abs(collider.SimPosition.X - currentPath.CurrentNode.SimPosition.X);
|
||||
bool isAboveFeet = currentPath.CurrentNode.SimPosition.Y > colliderBottom.Y;
|
||||
bool isNotTooHigh = currentPath.CurrentNode.SimPosition.Y < colliderBottom.Y + characterHeight;
|
||||
|
||||
@@ -132,7 +132,9 @@ namespace Barotrauma
|
||||
{
|
||||
if (Frozen) return;
|
||||
if (MainLimb == null) { return; }
|
||||
|
||||
|
||||
levitatingCollider = true;
|
||||
|
||||
if (!character.AllowInput)
|
||||
{
|
||||
levitatingCollider = false;
|
||||
@@ -542,8 +544,6 @@ namespace Barotrauma
|
||||
//limbs are disabled when simple physics is enabled, no need to move them
|
||||
if (SimplePhysicsEnabled) { return; }
|
||||
|
||||
float mainLimbHeight = ColliderHeightFromFloor;
|
||||
|
||||
Vector2 colliderBottom = GetColliderBottom();
|
||||
|
||||
float movementAngle = 0.0f;
|
||||
@@ -569,9 +569,9 @@ namespace Barotrauma
|
||||
Vector2 pos = colliderBottom + Vector2.UnitY * TorsoPosition.Value;
|
||||
|
||||
if (torso != MainLimb)
|
||||
{
|
||||
pos.X = torso.SimPosition.X;
|
||||
else
|
||||
mainLimbHeight = TorsoPosition.Value;
|
||||
}
|
||||
|
||||
torso.MoveToPos(pos, TorsoMoveForce);
|
||||
torso.PullJointEnabled = true;
|
||||
@@ -591,9 +591,9 @@ namespace Barotrauma
|
||||
Vector2 pos = colliderBottom + Vector2.UnitY * HeadPosition.Value;
|
||||
|
||||
if (head != MainLimb)
|
||||
{
|
||||
pos.X = head.SimPosition.X;
|
||||
else
|
||||
mainLimbHeight = HeadPosition.Value;
|
||||
}
|
||||
|
||||
head.MoveToPos(pos, HeadMoveForce);
|
||||
head.PullJointEnabled = true;
|
||||
|
||||
@@ -1298,7 +1298,8 @@ namespace Barotrauma
|
||||
|
||||
Vector2 colliderPos = GetColliderBottom();
|
||||
|
||||
bool wasCritical = target.Vitality < 0.0f;
|
||||
float prevVitality = target.Vitality;
|
||||
bool wasCritical = prevVitality < 0.0f;
|
||||
|
||||
if (GameMain.NetworkMember == null || !GameMain.NetworkMember.IsClient) //Serverside code
|
||||
{
|
||||
@@ -1357,7 +1358,7 @@ namespace Barotrauma
|
||||
AfflictionPrefab.InternalDamage.Instantiate((CPRSettings.DamageSkillThreshold - skill) * CPRSettings.DamageSkillMultiplier,
|
||||
source: character)
|
||||
},
|
||||
0.0f, true, 0.0f, character);
|
||||
0.0f, true, 0.0f, attacker: null);
|
||||
}
|
||||
if (GameMain.NetworkMember == null || !GameMain.NetworkMember.IsClient) //Serverside code
|
||||
{
|
||||
@@ -1389,9 +1390,12 @@ namespace Barotrauma
|
||||
character.Info.IncreaseSkillLevel("medical", 0.5f, character.WorldPosition + Vector2.UnitY * 150.0f);
|
||||
SteamAchievementManager.OnCharacterRevived(target, character);
|
||||
lastReviveTime = (float)Timing.TotalTime;
|
||||
#if SERVER
|
||||
GameMain.Server?.KarmaManager?.OnCharacterHealthChanged(target, character, damage: Math.Min(prevVitality - target.Vitality, 0.0f));
|
||||
#endif
|
||||
//reset attacker, we don't want the character to start attacking us
|
||||
//because we caused a bit of damage to them during CPR
|
||||
if (target.LastAttacker == character) target.LastAttacker = null;
|
||||
if (target.LastAttacker == character) { target.LastAttacker = null; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,150 +0,0 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using Microsoft.Xna.Framework.Input;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Xml;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
partial class HumanoidAnimParams : ISerializableEntity
|
||||
{
|
||||
public string Name
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public Dictionary<string, SerializableProperty> SerializableProperties
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public HumanoidAnimParams(string file)
|
||||
{
|
||||
XDocument doc = XMLExtensions.TryLoadXml(file);
|
||||
if (doc == null || doc.Root == null) return;
|
||||
|
||||
Name = doc.Root.Name.ToString();
|
||||
|
||||
SerializableProperties = SerializableProperty.DeserializeProperties(this, doc.Root);
|
||||
}
|
||||
|
||||
[Serialize(0.3f, true), Editable]
|
||||
public float GetUpSpeed
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
[Serialize(1.54f, true), Editable]
|
||||
public float HeadPosition
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
[Serialize(1.15f, true), Editable]
|
||||
public float TorsoPosition
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
|
||||
[Serialize(0.25f, true), Editable]
|
||||
public float HeadLeanAmount
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
[Serialize(0.25f, true), Editable]
|
||||
public float TorsoLeanAmount
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
[Serialize(5.0f, true), Editable]
|
||||
public float CycleSpeed
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
[Serialize(15.0f, true), Editable]
|
||||
public float FootMoveStrength
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
[Serialize(20.0f, true), Editable]
|
||||
public float FootRotateStrength
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
|
||||
[Serialize("0.4,0.12", true), Editable]
|
||||
public Vector2 StepSize
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
[Serialize("0.0, 0.0", true), Editable]
|
||||
public Vector2 FootMoveOffset
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
[Serialize(10.0f, true), Editable]
|
||||
public float LegCorrectionTorque
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
[Serialize(15.0f, true), Editable]
|
||||
public float ThighCorrectionTorque
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
[Serialize("0.4, 0.15", true), Editable]
|
||||
public Vector2 HandMoveAmount
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
[Serialize("-0.15, 0.0", true), Editable]
|
||||
public Vector2 HandMoveOffset
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
[Serialize(0.7f, true), Editable]
|
||||
public float HandMoveStrength
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
[Serialize(-1.0f, true), Editable]
|
||||
public float HandClampY
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1252,7 +1252,7 @@ namespace Barotrauma
|
||||
rayEnd.Y -= Collider.height * 0.5f + Collider.radius + ColliderHeightFromFloor*1.2f;
|
||||
|
||||
Vector2 colliderBottomDisplay = ConvertUnits.ToDisplayUnits(GetColliderBottom());
|
||||
if (!inWater && !character.IsDead && character.Stun <= 0f && levitatingCollider && Collider.LinearVelocity.Y>-ImpactTolerance)
|
||||
if (!inWater && !character.IsDead && character.Stun <= 0f && levitatingCollider && Collider.LinearVelocity.Y > -ImpactTolerance)
|
||||
{
|
||||
float closestFraction = 1.0f;
|
||||
Fixture closestFixture = null;
|
||||
|
||||
@@ -1484,6 +1484,9 @@ namespace Barotrauma
|
||||
return (wall == null || !wall.CastShadow) && (door == null || door.IsOpen);
|
||||
}
|
||||
|
||||
public bool HasItem(Item item, bool requireEquipped = false) =>
|
||||
requireEquipped ? HasEquippedItem(item) : item.FindParentInventory(i => i.Owner == this) != null;
|
||||
|
||||
public bool HasEquippedItem(Item item)
|
||||
{
|
||||
for (int i = 0; i < Inventory.Capacity; i++)
|
||||
@@ -1595,7 +1598,7 @@ namespace Barotrauma
|
||||
#if CLIENT
|
||||
if (Screen.Selected == GameMain.SubEditorScreen) { hidden = false; }
|
||||
#endif
|
||||
if (!CanInteract || hidden) return false;
|
||||
if (!CanInteract || hidden || item.NonInteractable) return false;
|
||||
|
||||
if (item.ParentInventory != null)
|
||||
{
|
||||
|
||||
@@ -764,13 +764,13 @@ namespace Barotrauma
|
||||
|
||||
public void SetSkillLevel(string skillIdentifier, float level, Vector2 worldPos)
|
||||
{
|
||||
if (Job == null) return;
|
||||
if (Job == null) { return; }
|
||||
|
||||
var skill = Job.Skills.Find(s => s.Identifier == skillIdentifier);
|
||||
if (skill == null)
|
||||
{
|
||||
Job.Skills.Add(new Skill(skillIdentifier, level));
|
||||
OnSkillChanged(skillIdentifier, 0.0f, skill.Level, worldPos);
|
||||
OnSkillChanged(skillIdentifier, 0.0f, level, worldPos);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -1,141 +0,0 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
class Affliction
|
||||
{
|
||||
public readonly AfflictionPrefab Prefab;
|
||||
|
||||
public float Strength;
|
||||
|
||||
public float DamagePerSecond;
|
||||
public float DamagePerSecondTimer;
|
||||
public float PreviousVitalityDecrease;
|
||||
|
||||
/// <summary>
|
||||
/// Which character gave this affliction
|
||||
/// </summary>
|
||||
public Character Source;
|
||||
|
||||
public Affliction(AfflictionPrefab prefab, float strength)
|
||||
{
|
||||
Prefab = prefab;
|
||||
Strength = strength;
|
||||
}
|
||||
|
||||
public Affliction CreateMultiplied(float multiplier)
|
||||
{
|
||||
return Prefab.Instantiate(Strength * multiplier, Source);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return "Affliction (" + Prefab.Name + ")";
|
||||
}
|
||||
|
||||
public float GetVitalityDecrease(CharacterHealth characterHealth)
|
||||
{
|
||||
if (Strength < Prefab.ActivationThreshold) return 0.0f;
|
||||
AfflictionPrefab.Effect currentEffect = Prefab.GetActiveEffect(Strength);
|
||||
if (currentEffect == null) return 0.0f;
|
||||
if (currentEffect.MaxStrength - currentEffect.MinStrength <= 0.0f) return 0.0f;
|
||||
|
||||
float currVitalityDecrease = MathHelper.Lerp(
|
||||
currentEffect.MinVitalityDecrease,
|
||||
currentEffect.MaxVitalityDecrease,
|
||||
(Strength - currentEffect.MinStrength) / (currentEffect.MaxStrength - currentEffect.MinStrength));
|
||||
|
||||
if (currentEffect.MultiplyByMaxVitality) currVitalityDecrease *= characterHealth == null ? 100.0f : characterHealth.MaxVitality;
|
||||
|
||||
return currVitalityDecrease;
|
||||
}
|
||||
|
||||
public float GetScreenDistortStrength()
|
||||
{
|
||||
if (Strength < Prefab.ActivationThreshold) return 0.0f;
|
||||
AfflictionPrefab.Effect currentEffect = Prefab.GetActiveEffect(Strength);
|
||||
if (currentEffect == null) return 0.0f;
|
||||
if (currentEffect.MaxScreenDistortStrength - currentEffect.MinScreenDistortStrength <= 0.0f) return 0.0f;
|
||||
|
||||
return MathHelper.Lerp(
|
||||
currentEffect.MinScreenDistortStrength,
|
||||
currentEffect.MaxScreenDistortStrength,
|
||||
(Strength - currentEffect.MinStrength) / (currentEffect.MaxStrength - currentEffect.MinStrength));
|
||||
}
|
||||
|
||||
public float GetRadialDistortStrength()
|
||||
{
|
||||
if (Strength < Prefab.ActivationThreshold) return 0.0f;
|
||||
AfflictionPrefab.Effect currentEffect = Prefab.GetActiveEffect(Strength);
|
||||
if (currentEffect == null) return 0.0f;
|
||||
if (currentEffect.MaxRadialDistortStrength - currentEffect.MinRadialDistortStrength <= 0.0f) return 0.0f;
|
||||
|
||||
return MathHelper.Lerp(
|
||||
currentEffect.MinRadialDistortStrength,
|
||||
currentEffect.MaxRadialDistortStrength,
|
||||
(Strength - currentEffect.MinStrength) / (currentEffect.MaxStrength - currentEffect.MinStrength));
|
||||
}
|
||||
|
||||
public float GetChromaticAberrationStrength()
|
||||
{
|
||||
if (Strength < Prefab.ActivationThreshold) return 0.0f;
|
||||
AfflictionPrefab.Effect currentEffect = Prefab.GetActiveEffect(Strength);
|
||||
if (currentEffect == null) return 0.0f;
|
||||
if (currentEffect.MaxChromaticAberrationStrength - currentEffect.MinChromaticAberrationStrength <= 0.0f) return 0.0f;
|
||||
|
||||
return MathHelper.Lerp(
|
||||
currentEffect.MinChromaticAberrationStrength,
|
||||
currentEffect.MaxChromaticAberrationStrength,
|
||||
(Strength - currentEffect.MinStrength) / (currentEffect.MaxStrength - currentEffect.MinStrength));
|
||||
}
|
||||
|
||||
public float GetScreenBlurStrength()
|
||||
{
|
||||
if (Strength < Prefab.ActivationThreshold) return 0.0f;
|
||||
AfflictionPrefab.Effect currentEffect = Prefab.GetActiveEffect(Strength);
|
||||
if (currentEffect == null) return 0.0f;
|
||||
if (currentEffect.MaxScreenBlurStrength - currentEffect.MinScreenBlurStrength <= 0.0f) return 0.0f;
|
||||
|
||||
return MathHelper.Lerp(
|
||||
currentEffect.MinScreenBlurStrength,
|
||||
currentEffect.MaxScreenBlurStrength,
|
||||
(Strength - currentEffect.MinStrength) / (currentEffect.MaxStrength - currentEffect.MinStrength));
|
||||
}
|
||||
|
||||
public void CalculateDamagePerSecond(float currentVitalityDecrease)
|
||||
{
|
||||
DamagePerSecond = Math.Max(DamagePerSecond, currentVitalityDecrease - PreviousVitalityDecrease);
|
||||
if (DamagePerSecondTimer >= 1.0f)
|
||||
{
|
||||
DamagePerSecond = currentVitalityDecrease - PreviousVitalityDecrease;
|
||||
PreviousVitalityDecrease = currentVitalityDecrease;
|
||||
DamagePerSecondTimer = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void Update(CharacterHealth characterHealth, Limb targetLimb, float deltaTime)
|
||||
{
|
||||
AfflictionPrefab.Effect currentEffect = Prefab.GetActiveEffect(Strength);
|
||||
if (currentEffect == null) return;
|
||||
|
||||
Strength += currentEffect.StrengthChange * deltaTime;
|
||||
foreach (StatusEffect statusEffect in currentEffect.StatusEffects)
|
||||
{
|
||||
if (statusEffect.HasTargetType(StatusEffect.TargetType.Character))
|
||||
{
|
||||
statusEffect.Apply(ActionType.OnActive, deltaTime, characterHealth.Character, characterHealth.Character);
|
||||
}
|
||||
if (targetLimb != null && statusEffect.HasTargetType(StatusEffect.TargetType.Limb))
|
||||
{
|
||||
statusEffect.Apply(ActionType.OnActive, deltaTime, characterHealth.Character, targetLimb);
|
||||
}
|
||||
if (targetLimb != null && statusEffect.HasTargetType(StatusEffect.TargetType.AllLimbs))
|
||||
{
|
||||
statusEffect.Apply(ActionType.OnActive, deltaTime, targetLimb.character, targetLimb.character.AnimController.Limbs.Cast<ISerializableEntity>().ToList());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
class AfflictionBleeding : Affliction
|
||||
{
|
||||
public AfflictionBleeding(AfflictionPrefab prefab, float strength) :
|
||||
base(prefab, strength)
|
||||
{
|
||||
}
|
||||
|
||||
public override void Update(CharacterHealth characterHealth, Limb targetLimb, float deltaTime)
|
||||
{
|
||||
base.Update(characterHealth, targetLimb, deltaTime);
|
||||
characterHealth.BloodlossAmount += Strength * (1.0f / 60.0f) * deltaTime;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,336 +0,0 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
public static class CPRSettings
|
||||
{
|
||||
public static float ReviveChancePerSkill { get; private set; }
|
||||
public static float ReviveChanceExponent { get; private set; }
|
||||
public static float ReviveChanceMin { get; private set; }
|
||||
public static float ReviveChanceMax { get; private set; }
|
||||
public static float StabilizationPerSkill { get; private set; }
|
||||
public static float StabilizationMin { get; private set; }
|
||||
public static float StabilizationMax { get; private set; }
|
||||
public static float DamageSkillThreshold { get; private set; }
|
||||
public static float DamageSkillMultiplier { get; private set; }
|
||||
|
||||
public static void Load(XElement element)
|
||||
{
|
||||
ReviveChancePerSkill = Math.Max(element.GetAttributeFloat("revivechanceperskill", 0.01f), 0.0f);
|
||||
ReviveChanceExponent = Math.Max(element.GetAttributeFloat("revivechanceexponent", 2.0f), 0.0f);
|
||||
ReviveChanceMin = MathHelper.Clamp(element.GetAttributeFloat("revivechancemin", 0.05f), 0.0f, 1.0f);
|
||||
ReviveChanceMax = MathHelper.Clamp(element.GetAttributeFloat("revivechancemax", 0.9f), ReviveChanceMin, 1.0f);
|
||||
|
||||
StabilizationPerSkill = Math.Max(element.GetAttributeFloat("stabilizationperskill", 0.01f), 0.0f);
|
||||
StabilizationMin = MathHelper.Max(element.GetAttributeFloat("stabilizationmin", 0.05f), 0.0f);
|
||||
StabilizationMax = MathHelper.Max(element.GetAttributeFloat("stabilizationmax", 2.0f), StabilizationMin);
|
||||
|
||||
DamageSkillThreshold = MathHelper.Clamp(element.GetAttributeFloat("damageskillthreshold", 40.0f), 0.0f, 100.0f);
|
||||
DamageSkillMultiplier = MathHelper.Clamp(element.GetAttributeFloat("damageskillmultiplier", 0.1f), 0.0f, 100.0f);
|
||||
}
|
||||
}
|
||||
|
||||
class AfflictionPrefab
|
||||
{
|
||||
public class Effect
|
||||
{
|
||||
//this effect is applied when the strength is within this range
|
||||
public float MinStrength, MaxStrength;
|
||||
|
||||
public readonly float MinVitalityDecrease = 0.0f;
|
||||
public readonly float MaxVitalityDecrease = 0.0f;
|
||||
|
||||
//how much the strength of the affliction changes per second
|
||||
public readonly float StrengthChange = 0.0f;
|
||||
|
||||
public readonly bool MultiplyByMaxVitality;
|
||||
|
||||
public float MinScreenBlurStrength, MaxScreenBlurStrength;
|
||||
public float MinScreenDistortStrength, MaxScreenDistortStrength;
|
||||
public float MinRadialDistortStrength, MaxRadialDistortStrength;
|
||||
public float MinChromaticAberrationStrength, MaxChromaticAberrationStrength;
|
||||
|
||||
public string DialogFlag;
|
||||
|
||||
//statuseffects applied on the character when the affliction is active
|
||||
public readonly List<StatusEffect> StatusEffects = new List<StatusEffect>();
|
||||
|
||||
public Effect(XElement element, string parentDebugName)
|
||||
{
|
||||
MinStrength = element.GetAttributeFloat("minstrength", 0);
|
||||
MaxStrength = element.GetAttributeFloat("maxstrength", 0);
|
||||
|
||||
MultiplyByMaxVitality = element.GetAttributeBool("multiplybymaxvitality", false);
|
||||
|
||||
MinVitalityDecrease = element.GetAttributeFloat("minvitalitydecrease", 0.0f);
|
||||
MaxVitalityDecrease = element.GetAttributeFloat("maxvitalitydecrease", 0.0f);
|
||||
MaxVitalityDecrease = Math.Max(MinVitalityDecrease, MaxVitalityDecrease);
|
||||
|
||||
MinScreenDistortStrength = element.GetAttributeFloat("minscreendistort", 0.0f);
|
||||
MaxScreenDistortStrength = element.GetAttributeFloat("maxscreendistort", 0.0f);
|
||||
MaxScreenDistortStrength = Math.Max(MinScreenDistortStrength, MaxScreenDistortStrength);
|
||||
|
||||
MinRadialDistortStrength = element.GetAttributeFloat("minradialdistort", 0.0f);
|
||||
MaxRadialDistortStrength = element.GetAttributeFloat("maxradialdistort", 0.0f);
|
||||
MaxRadialDistortStrength = Math.Max(MinRadialDistortStrength, MaxRadialDistortStrength);
|
||||
|
||||
MinChromaticAberrationStrength = element.GetAttributeFloat("minchromaticaberration", 0.0f);
|
||||
MaxChromaticAberrationStrength = element.GetAttributeFloat("maxchromaticaberration", 0.0f);
|
||||
MaxChromaticAberrationStrength = Math.Max(MinChromaticAberrationStrength, MaxChromaticAberrationStrength);
|
||||
|
||||
MinScreenBlurStrength = element.GetAttributeFloat("minscreenblur", 0.0f);
|
||||
MaxScreenBlurStrength = element.GetAttributeFloat("maxscreenblur", 0.0f);
|
||||
MaxScreenBlurStrength = Math.Max(MinScreenBlurStrength, MaxScreenBlurStrength);
|
||||
|
||||
DialogFlag = element.GetAttributeString("dialogflag", "");
|
||||
|
||||
StrengthChange = element.GetAttributeFloat("strengthchange", 0.0f);
|
||||
|
||||
foreach (XElement subElement in element.Elements())
|
||||
{
|
||||
switch (subElement.Name.ToString().ToLowerInvariant())
|
||||
{
|
||||
case "statuseffect":
|
||||
StatusEffects.Add(StatusEffect.Load(subElement, parentDebugName));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static AfflictionPrefab InternalDamage;
|
||||
public static AfflictionPrefab Bleeding;
|
||||
public static AfflictionPrefab Burn;
|
||||
public static AfflictionPrefab OxygenLow;
|
||||
public static AfflictionPrefab Bloodloss;
|
||||
public static AfflictionPrefab Pressure;
|
||||
public static AfflictionPrefab Stun;
|
||||
public static AfflictionPrefab Husk;
|
||||
|
||||
public static List<AfflictionPrefab> List = new List<AfflictionPrefab>();
|
||||
|
||||
//Arbitrary string that is used to identify the type of the affliction.
|
||||
//Afflictions with the same type stack up, and items may be configured to cure specific types of afflictions.
|
||||
public readonly string AfflictionType;
|
||||
|
||||
//Does the affliction affect a specific limb or the whole character
|
||||
public readonly bool LimbSpecific;
|
||||
|
||||
//If not a limb-specific affliction, which limb is the indicator shown on in the health menu
|
||||
//(e.g. mental health problems on head, lack of oxygen on torso...)
|
||||
public readonly LimbType IndicatorLimb;
|
||||
|
||||
public readonly string Identifier;
|
||||
|
||||
public readonly string Name, Description;
|
||||
|
||||
public readonly string CauseOfDeathDescription, SelfCauseOfDeathDescription;
|
||||
|
||||
//how high the strength has to be for the affliction to take affect
|
||||
public readonly float ActivationThreshold = 0.0f;
|
||||
//how high the strength has to be for the affliction icon to be shown in the UI
|
||||
public readonly float ShowIconThreshold = 0.0f;
|
||||
public readonly float MaxStrength = 100.0f;
|
||||
|
||||
public float BurnOverlayAlpha;
|
||||
public float DamageOverlayAlpha;
|
||||
|
||||
//steam achievement given when the affliction is removed from the controlled character
|
||||
public readonly string AchievementOnRemoved;
|
||||
|
||||
public readonly Sprite Icon;
|
||||
public readonly Color IconColor;
|
||||
|
||||
private List<Effect> effects = new List<Effect>();
|
||||
|
||||
private Dictionary<string, float> treatmentSuitability = new Dictionary<string, float>();
|
||||
|
||||
private readonly string typeName;
|
||||
|
||||
private readonly ConstructorInfo constructor;
|
||||
|
||||
public Dictionary<string, float> TreatmentSuitability
|
||||
{
|
||||
get { return treatmentSuitability; }
|
||||
}
|
||||
|
||||
public static void LoadAll(IEnumerable<string> filePaths)
|
||||
{
|
||||
foreach (string filePath in filePaths)
|
||||
{
|
||||
XDocument doc = XMLExtensions.TryLoadXml(filePath);
|
||||
if (doc == null || doc.Root == null) continue;
|
||||
|
||||
foreach (XElement element in doc.Root.Elements())
|
||||
{
|
||||
switch (element.Name.ToString().ToLowerInvariant())
|
||||
{
|
||||
case "internaldamage":
|
||||
List.Add(InternalDamage = new AfflictionPrefab(element, typeof(Affliction)));
|
||||
break;
|
||||
case "bleeding":
|
||||
List.Add(Bleeding = new AfflictionPrefab(element, typeof(AfflictionBleeding)));
|
||||
break;
|
||||
case "burn":
|
||||
List.Add(Burn = new AfflictionPrefab(element, typeof(Affliction)));
|
||||
break;
|
||||
case "oxygenlow":
|
||||
List.Add(OxygenLow = new AfflictionPrefab(element, typeof(Affliction)));
|
||||
break;
|
||||
case "bloodloss":
|
||||
List.Add(Bloodloss = new AfflictionPrefab(element, typeof(Affliction)));
|
||||
break;
|
||||
case "pressure":
|
||||
List.Add(Pressure = new AfflictionPrefab(element, typeof(Affliction)));
|
||||
break;
|
||||
case "stun":
|
||||
List.Add(Stun = new AfflictionPrefab(element, typeof(Affliction)));
|
||||
break;
|
||||
case "husk":
|
||||
case "afflictionhusk":
|
||||
List.Add(Husk = new AfflictionPrefab(element, typeof(AfflictionHusk)));
|
||||
break;
|
||||
case "cprsettings":
|
||||
CPRSettings.Load(element);
|
||||
break;
|
||||
default:
|
||||
List.Add(new AfflictionPrefab(element));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (InternalDamage == null) DebugConsole.ThrowError("Affliction \"Internal Damage\" not defined in the affliction prefabs.");
|
||||
if (Bleeding == null) DebugConsole.ThrowError("Affliction \"Bleeding\" not defined in the affliction prefabs.");
|
||||
if (Burn == null) DebugConsole.ThrowError("Affliction \"Burn\" not defined in the affliction prefabs.");
|
||||
if (OxygenLow == null) DebugConsole.ThrowError("Affliction \"OxygenLow\" not defined in the affliction prefabs.");
|
||||
if (Bloodloss == null) DebugConsole.ThrowError("Affliction \"Bloodloss\" not defined in the affliction prefabs.");
|
||||
if (Pressure == null) DebugConsole.ThrowError("Affliction \"Pressure\" not defined in the affliction prefabs.");
|
||||
if (Stun == null) DebugConsole.ThrowError("Affliction \"Stun\" not defined in the affliction prefabs.");
|
||||
if (Husk == null) DebugConsole.ThrowError("Affliction \"Husk\" not defined in the affliction prefabs.");
|
||||
}
|
||||
|
||||
public AfflictionPrefab(XElement element, Type type = null)
|
||||
{
|
||||
typeName = type == null ? element.Name.ToString() : type.Name;
|
||||
|
||||
Identifier = element.GetAttributeString("identifier", "");
|
||||
|
||||
AfflictionType = element.GetAttributeString("type", "");
|
||||
Name = TextManager.Get("AfflictionName." + Identifier, true) ?? element.GetAttributeString("name", "");
|
||||
Description = TextManager.Get("AfflictionDescription." + Identifier, true) ?? element.GetAttributeString("description", "");
|
||||
|
||||
LimbSpecific = element.GetAttributeBool("limbspecific", false);
|
||||
if (!LimbSpecific)
|
||||
{
|
||||
string indicatorLimbName = element.GetAttributeString("indicatorlimb", "Torso");
|
||||
if (!Enum.TryParse(indicatorLimbName, out IndicatorLimb))
|
||||
{
|
||||
DebugConsole.ThrowError("Error in affliction prefab " + Name + " - limb type \"" + indicatorLimbName + "\" not found.");
|
||||
}
|
||||
}
|
||||
|
||||
ActivationThreshold = element.GetAttributeFloat("activationthreshold", 0.0f);
|
||||
ShowIconThreshold = element.GetAttributeFloat("showiconthreshold", ActivationThreshold);
|
||||
MaxStrength = element.GetAttributeFloat("maxstrength", 100.0f);
|
||||
|
||||
DamageOverlayAlpha = element.GetAttributeFloat("damageoverlayalpha", 0.0f);
|
||||
BurnOverlayAlpha = element.GetAttributeFloat("burnoverlayalpha", 0.0f);
|
||||
|
||||
CauseOfDeathDescription = TextManager.Get("AfflictionCauseOfDeath." + Identifier, true) ?? element.GetAttributeString("causeofdeathdescription", "");
|
||||
SelfCauseOfDeathDescription = TextManager.Get("AfflictionCauseOfDeathSelf." + Identifier, true) ?? element.GetAttributeString("selfcauseofdeathdescription", "");
|
||||
|
||||
AchievementOnRemoved = element.GetAttributeString("achievementonremoved", "");
|
||||
|
||||
foreach (XElement subElement in element.Elements())
|
||||
{
|
||||
switch (subElement.Name.ToString().ToLowerInvariant())
|
||||
{
|
||||
case "icon":
|
||||
Icon = new Sprite(subElement);
|
||||
IconColor = subElement.GetAttributeColor("color", Color.White);
|
||||
break;
|
||||
case "effect":
|
||||
effects.Add(new Effect(subElement, Name));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (type == null)
|
||||
{
|
||||
type = Type.GetType("Barotrauma." + typeName, true, true);
|
||||
if (type == null)
|
||||
{
|
||||
DebugConsole.ThrowError("Could not find an affliction class of the type \"" + typeName + "\".");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
DebugConsole.ThrowError("Could not find an affliction class of the type \"" + typeName + "\".");
|
||||
return;
|
||||
}
|
||||
|
||||
constructor = type.GetConstructor(new[] { typeof(AfflictionPrefab), typeof(float) });
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return "AfflictionPrefab (" + Name + ")";
|
||||
}
|
||||
|
||||
public Affliction Instantiate(float strength, Character source = null)
|
||||
{
|
||||
object instance = null;
|
||||
try
|
||||
{
|
||||
instance = constructor.Invoke(new object[] { this, strength });
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
DebugConsole.ThrowError(ex.InnerException != null ? ex.InnerException.ToString() : ex.ToString());
|
||||
}
|
||||
Affliction affliction = instance as Affliction;
|
||||
affliction.Source = source;
|
||||
return affliction;
|
||||
}
|
||||
|
||||
public Effect GetActiveEffect(float currentStrength)
|
||||
{
|
||||
foreach (Effect effect in effects)
|
||||
{
|
||||
if (currentStrength > effect.MinStrength && currentStrength <= effect.MaxStrength) return effect;
|
||||
}
|
||||
|
||||
//if above the strength range of all effects, use the highest strength effect
|
||||
Effect strongestEffect = null;
|
||||
float largestStrength = currentStrength;
|
||||
foreach (Effect effect in effects)
|
||||
{
|
||||
if (currentStrength > effect.MaxStrength &&
|
||||
(strongestEffect == null || effect.MaxStrength > largestStrength))
|
||||
{
|
||||
strongestEffect = effect;
|
||||
largestStrength = effect.MaxStrength;
|
||||
}
|
||||
}
|
||||
return strongestEffect;
|
||||
}
|
||||
|
||||
public float GetTreatmentSuitability(Item item)
|
||||
{
|
||||
if (item == null || !treatmentSuitability.ContainsKey(item.Prefab.Identifier.ToLowerInvariant()))
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
return treatmentSuitability[item.Prefab.Identifier.ToLowerInvariant()];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Barotrauma.Extensions;
|
||||
using System.Xml.Linq;
|
||||
using System;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
partial class AfflictionPsychosis : Affliction
|
||||
{
|
||||
|
||||
public AfflictionPsychosis(AfflictionPrefab prefab, float strength) : base(prefab, strength)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public override void Update(CharacterHealth characterHealth, Limb targetLimb, float deltaTime)
|
||||
{
|
||||
base.Update(characterHealth, targetLimb, deltaTime);
|
||||
UpdateProjSpecific(characterHealth, targetLimb, deltaTime);
|
||||
}
|
||||
|
||||
partial void UpdateProjSpecific(CharacterHealth characterHealth, Limb targetLimb, float deltaTime);
|
||||
}
|
||||
}
|
||||
@@ -739,7 +739,7 @@ namespace Barotrauma
|
||||
msg.Write((byte)activeAfflictions.Count);
|
||||
foreach (Affliction affliction in activeAfflictions)
|
||||
{
|
||||
msg.WriteRangedIntegerDeprecated(0, AfflictionPrefab.List.Count - 1, AfflictionPrefab.List.IndexOf(affliction.Prefab));
|
||||
msg.WriteRangedInteger(AfflictionPrefab.List.IndexOf(affliction.Prefab), 0, AfflictionPrefab.List.Count - 1);
|
||||
msg.WriteRangedSingle(
|
||||
MathHelper.Clamp(affliction.Strength, 0.0f, affliction.Prefab.MaxStrength),
|
||||
0.0f, affliction.Prefab.MaxStrength, 8);
|
||||
@@ -758,8 +758,8 @@ namespace Barotrauma
|
||||
msg.Write((byte)limbAfflictions.Count);
|
||||
foreach (var limbAffliction in limbAfflictions)
|
||||
{
|
||||
msg.WriteRangedIntegerDeprecated(0, limbHealths.Count - 1, limbHealths.IndexOf(limbAffliction.First));
|
||||
msg.WriteRangedIntegerDeprecated(0, AfflictionPrefab.List.Count - 1, AfflictionPrefab.List.IndexOf(limbAffliction.Second.Prefab));
|
||||
msg.WriteRangedInteger(limbHealths.IndexOf(limbAffliction.First), 0, limbHealths.Count - 1);
|
||||
msg.WriteRangedInteger(AfflictionPrefab.List.IndexOf(limbAffliction.Second.Prefab), 0, AfflictionPrefab.List.Count - 1);
|
||||
msg.WriteRangedSingle(
|
||||
MathHelper.Clamp(limbAffliction.Second.Strength, 0.0f, limbAffliction.Second.Prefab.MaxStrength),
|
||||
0.0f, limbAffliction.Second.Prefab.MaxStrength, 8);
|
||||
|
||||
@@ -90,6 +90,7 @@ namespace Barotrauma.Items.Components
|
||||
item.body.FarseerBody.CollisionCategories = Physics.CollisionProjectile;
|
||||
item.body.FarseerBody.CollidesWith = Physics.CollisionCharacter | Physics.CollisionWall;
|
||||
item.body.FarseerBody.OnCollision += OnCollision;
|
||||
item.body.FarseerBody.IsBullet = true;
|
||||
|
||||
if (!character.AnimController.InWater)
|
||||
{
|
||||
@@ -207,9 +208,9 @@ namespace Barotrauma.Items.Components
|
||||
private void RestoreCollision()
|
||||
{
|
||||
item.body.FarseerBody.OnCollision -= OnCollision;
|
||||
|
||||
item.body.CollisionCategories = Physics.CollisionItem;
|
||||
item.body.CollidesWith = Physics.CollisionWall;
|
||||
item.body.FarseerBody.IsBullet = false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -132,7 +132,7 @@ namespace Barotrauma.Items.Components
|
||||
return false;
|
||||
}
|
||||
|
||||
if (character.AnimController.InWater)
|
||||
if (item.InWater)
|
||||
{
|
||||
if (UsableIn == UseEnvironment.Air)
|
||||
{
|
||||
@@ -160,7 +160,8 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
else
|
||||
{
|
||||
rayStart = ConvertUnits.ToSimUnits(item.WorldPosition);
|
||||
rayStart = Submarine.LastPickedPosition + Submarine.LastPickedNormal * 0.1f;
|
||||
if (item.Submarine != null) { rayStart += item.Submarine.SimPosition; }
|
||||
}
|
||||
|
||||
Vector2 rayEnd = rayStart +
|
||||
@@ -201,12 +202,12 @@ namespace Barotrauma.Items.Components
|
||||
Repair(rayStart - character.Submarine.SimPosition, rayEnd - character.Submarine.SimPosition, deltaTime, character, degreeOfSuccess, ignoredBodies);
|
||||
}
|
||||
|
||||
UseProjSpecific(deltaTime);
|
||||
UseProjSpecific(deltaTime, rayStart);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
partial void UseProjSpecific(float deltaTime);
|
||||
partial void UseProjSpecific(float deltaTime, Vector2 raystart);
|
||||
|
||||
private readonly HashSet<Character> hitCharacters = new HashSet<Character>();
|
||||
private readonly List<FireSource> fireSourcesInRange = new List<FireSource>();
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using FarseerPhysics;
|
||||
using Barotrauma.Networking;
|
||||
using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
@@ -19,7 +20,7 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
|
||||
partial class Controller : ItemComponent
|
||||
partial class Controller : ItemComponent, IServerSerializable
|
||||
{
|
||||
//where the limbs of the user should be positioned when using the controller
|
||||
private List<LimbPos> limbPositions;
|
||||
@@ -270,17 +271,21 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
if (IsToggle)
|
||||
{
|
||||
state = !state;
|
||||
if (GameMain.NetworkMember == null || GameMain.NetworkMember.IsServer)
|
||||
{
|
||||
state = !state;
|
||||
#if SERVER
|
||||
item.CreateServerEvent(this);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
item.SendSignal(0, "1", "signal_out", picker);
|
||||
}
|
||||
|
||||
#if CLIENT
|
||||
PlaySound(ActionType.OnUse, item.WorldPosition, picker);
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -273,14 +273,18 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
if (connection.Name == "set_rate")
|
||||
{
|
||||
float tempSpeed;
|
||||
if (float.TryParse(signal, NumberStyles.Any, CultureInfo.InvariantCulture, out tempSpeed))
|
||||
if (float.TryParse(signal, NumberStyles.Any, CultureInfo.InvariantCulture, out float tempSpeed))
|
||||
{
|
||||
if (!MathUtils.IsValid(tempSpeed)) return;
|
||||
RechargeSpeed = MathHelper.Clamp(tempSpeed / 100.0f, 0.0f, 1.0f) * MaxRechargeSpeed;
|
||||
if (!MathUtils.IsValid(tempSpeed)) { return; }
|
||||
|
||||
float rechargeRate = MathHelper.Clamp(tempSpeed / 100.0f, 0.0f, 1.0f);
|
||||
RechargeSpeed = rechargeRate * MaxRechargeSpeed;
|
||||
#if CLIENT
|
||||
rechargeSpeedSlider.BarScroll = rechargeRate;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
if (!connection.IsPower) return;
|
||||
if (!connection.IsPower) { return; }
|
||||
|
||||
if (connection.Name == "power_in")
|
||||
{
|
||||
|
||||
@@ -146,6 +146,10 @@ namespace Barotrauma.Items.Components
|
||||
currentFixerAction = FixActions.None;
|
||||
#if SERVER
|
||||
item.CreateServerEvent(this);
|
||||
#endif
|
||||
#if CLIENT
|
||||
repairSoundChannel?.FadeOutAndDispose();
|
||||
repairSoundChannel = null;
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
@@ -221,8 +225,8 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient) { return; }
|
||||
|
||||
float successFactor = requiredSkills.Count == 0 ? 1.0f : 0.0f;
|
||||
|
||||
float successFactor = requiredSkills.Count == 0 ? 1.0f : DegreeOfSuccess(CurrentFixer, requiredSkills);
|
||||
|
||||
//item must have been below the repair threshold for the player to get an achievement or XP for repairing it
|
||||
if (item.ConditionPercentage < ShowRepairUIThreshold)
|
||||
{
|
||||
|
||||
@@ -122,22 +122,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
public override void Update(float deltaTime, Camera cam)
|
||||
{
|
||||
#if CLIENT
|
||||
foreach (Wire wire in DisconnectedWires)
|
||||
{
|
||||
if (Rand.Range(0.0f, 500.0f) < 1.0f)
|
||||
{
|
||||
SoundPlayer.PlaySound("zap", item.WorldPosition, hullGuess: item.CurrentHull);
|
||||
Vector2 baseVel = new Vector2(0.0f, -100.0f);
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
var particle = GameMain.ParticleManager.CreateParticle("spark", item.WorldPosition,
|
||||
baseVel + Rand.Vector(100.0f), 0.0f, item.CurrentHull);
|
||||
if (particle != null) { particle.Size *= Rand.Range(0.5f, 1.0f); }
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
UpdateProjSpecific(deltaTime);
|
||||
|
||||
if (user == null || user.SelectedConstruction != item)
|
||||
{
|
||||
@@ -150,6 +135,8 @@ namespace Barotrauma.Items.Components
|
||||
user.AnimController.UpdateUseItem(true, item.WorldPosition + new Vector2(0.0f, 100.0f) * (((float)Timing.TotalTime / 10.0f) % 0.1f));
|
||||
}
|
||||
|
||||
partial void UpdateProjSpecific(float deltaTime);
|
||||
|
||||
public override bool Select(Character picker)
|
||||
{
|
||||
//attaching wires to items with a body is not allowed
|
||||
@@ -260,8 +247,14 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if CLIENT
|
||||
rewireSoundChannel?.FadeOutAndDispose();
|
||||
rewireSoundChannel = null;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
public void ClientWrite(IWriteMessage msg, object[] extraData = null)
|
||||
{
|
||||
foreach (Connection connection in Connections)
|
||||
|
||||
@@ -160,6 +160,14 @@ namespace Barotrauma.Items.Components
|
||||
item.AddTag("light");
|
||||
}
|
||||
|
||||
#if CLIENT
|
||||
public override void OnScaleChanged()
|
||||
{
|
||||
light.SpriteScale = Vector2.One * item.Scale;
|
||||
light.Position = ParentBody != null ? ParentBody.Position : item.Position;
|
||||
}
|
||||
#endif
|
||||
|
||||
public override void OnItemLoaded()
|
||||
{
|
||||
base.OnItemLoaded();
|
||||
@@ -175,7 +183,6 @@ namespace Barotrauma.Items.Components
|
||||
UpdateOnActiveEffects(deltaTime);
|
||||
|
||||
#if CLIENT
|
||||
light.SpriteScale = Vector2.One * item.Scale;
|
||||
light.ParentSub = item.Submarine;
|
||||
if (item.Container != null)
|
||||
{
|
||||
|
||||
@@ -336,30 +336,39 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
public Item FindItemByTag(string tag)
|
||||
public Item FindItem(Func<Item, bool> predicate, bool recursive)
|
||||
{
|
||||
if (tag == null) return null;
|
||||
return Items.FirstOrDefault(i => i != null && i.HasTag(tag));
|
||||
Item match = Items.FirstOrDefault(predicate);
|
||||
if (match == null && recursive)
|
||||
{
|
||||
foreach (var item in Items)
|
||||
{
|
||||
if (item == null) { continue; }
|
||||
if (item.OwnInventory != null)
|
||||
{
|
||||
match = item.OwnInventory.FindItem(predicate, true);
|
||||
if (match != null)
|
||||
{
|
||||
return match;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return match;
|
||||
}
|
||||
|
||||
public Item FindItemByIdentifier(string identifier)
|
||||
public Item FindItemByTag(string tag, bool recursive = false)
|
||||
{
|
||||
if (tag == null) { return null; }
|
||||
return FindItem(i => i != null && i.HasTag(tag), recursive);
|
||||
}
|
||||
|
||||
public Item FindItemByIdentifier(string identifier, bool recursive = false)
|
||||
{
|
||||
if (identifier == null) return null;
|
||||
return Items.FirstOrDefault(i => i != null && i.Prefab.Identifier == identifier);
|
||||
return FindItem(i => i != null && i.Prefab.Identifier == identifier, recursive);
|
||||
}
|
||||
|
||||
/*public Item FindItem(string[] itemNames)
|
||||
{
|
||||
if (itemNames == null) return null;
|
||||
|
||||
foreach (string itemName in itemNames)
|
||||
{
|
||||
var item = FindItem(itemName);
|
||||
if (item != null) return item;
|
||||
}
|
||||
return null;
|
||||
}*/
|
||||
|
||||
public virtual void RemoveItem(Item item)
|
||||
{
|
||||
if (item == null) return;
|
||||
@@ -376,6 +385,7 @@ namespace Barotrauma
|
||||
|
||||
public void SharedWrite(IWriteMessage msg, object[] extraData = null)
|
||||
{
|
||||
msg.Write((byte)capacity);
|
||||
for (int i = 0; i < capacity; i++)
|
||||
{
|
||||
msg.Write((ushort)(Items[i] == null ? 0 : Items[i].ID));
|
||||
|
||||
@@ -126,24 +126,6 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
public delegate bool InventoryFilter(Inventory inventory);
|
||||
public Inventory FindParentInventory(InventoryFilter filter)
|
||||
{
|
||||
if (parentInventory != null)
|
||||
{
|
||||
if (filter(parentInventory))
|
||||
{
|
||||
return parentInventory;
|
||||
}
|
||||
var owner = parentInventory.Owner as Item;
|
||||
if (owner != null)
|
||||
{
|
||||
return owner.FindParentInventory(filter);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private Item container;
|
||||
public Item Container
|
||||
{
|
||||
@@ -177,6 +159,13 @@ namespace Barotrauma
|
||||
set;
|
||||
}
|
||||
|
||||
[Editable, Serialize(false, true)]
|
||||
public bool NonInteractable
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public float ImpactTolerance
|
||||
{
|
||||
get { return Prefab.ImpactTolerance; }
|
||||
@@ -398,6 +387,7 @@ namespace Barotrauma
|
||||
}
|
||||
else if (!MathUtils.NearlyEqual(lastSentCondition, condition) && (condition <= 0.0f || condition >= Prefab.Health))
|
||||
{
|
||||
sendConditionUpdateTimer = 0.0f;
|
||||
conditionUpdatePending = true;
|
||||
}
|
||||
}
|
||||
@@ -955,7 +945,6 @@ namespace Barotrauma
|
||||
return CurrentHull;
|
||||
}
|
||||
|
||||
|
||||
CurrentHull = Hull.FindHull(WorldPosition, CurrentHull);
|
||||
if (body != null && body.Enabled)
|
||||
{
|
||||
@@ -978,7 +967,23 @@ namespace Barotrauma
|
||||
|
||||
return rootContainer;
|
||||
}
|
||||
|
||||
|
||||
public Inventory FindParentInventory(Func<Inventory, bool> predicate)
|
||||
{
|
||||
if (parentInventory != null)
|
||||
{
|
||||
if (predicate(parentInventory))
|
||||
{
|
||||
return parentInventory;
|
||||
}
|
||||
if (parentInventory.Owner is Item owner)
|
||||
{
|
||||
return owner.FindParentInventory(predicate);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void SetContainedItemPositions()
|
||||
{
|
||||
foreach (ItemComponent component in components)
|
||||
@@ -1137,6 +1142,17 @@ namespace Barotrauma
|
||||
return CurrentHull.WaterVolume > 0.0f && Position.Y < surfaceY;
|
||||
}
|
||||
|
||||
public void SendPendingNetworkUpdates()
|
||||
{
|
||||
if (GameMain.NetworkMember == null || !GameMain.NetworkMember.IsServer) { return; }
|
||||
if (conditionUpdatePending)
|
||||
{
|
||||
GameMain.NetworkMember.CreateEntityEvent(this, new object[] { NetEntityEvent.Type.Status });
|
||||
lastSentCondition = condition;
|
||||
sendConditionUpdateTimer = NetConfig.ItemConditionUpdateInterval;
|
||||
conditionUpdatePending = false;
|
||||
}
|
||||
}
|
||||
|
||||
public override void Update(float deltaTime, Camera cam)
|
||||
{
|
||||
@@ -1153,16 +1169,10 @@ namespace Barotrauma
|
||||
if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsServer)
|
||||
{
|
||||
sendConditionUpdateTimer -= deltaTime;
|
||||
if (conditionUpdatePending)
|
||||
if (conditionUpdatePending && sendConditionUpdateTimer <= 0.0f)
|
||||
{
|
||||
if (sendConditionUpdateTimer <= 0.0f)
|
||||
{
|
||||
GameMain.NetworkMember.CreateEntityEvent(this, new object[] { NetEntityEvent.Type.Status });
|
||||
lastSentCondition = condition;
|
||||
sendConditionUpdateTimer = NetConfig.ItemConditionUpdateInterval;
|
||||
conditionUpdatePending = false;
|
||||
}
|
||||
}
|
||||
SendPendingNetworkUpdates();
|
||||
}
|
||||
}
|
||||
|
||||
ApplyStatusEffects(ActionType.Always, deltaTime, null);
|
||||
@@ -1878,7 +1888,7 @@ namespace Barotrauma
|
||||
var propertyOwner = allProperties.Find(p => p.Second == property);
|
||||
if (allProperties.Count > 1)
|
||||
{
|
||||
msg.WriteRangedIntegerDeprecated(0, allProperties.Count - 1, allProperties.FindIndex(p => p.Second == property));
|
||||
msg.WriteRangedInteger(allProperties.FindIndex(p => p.Second == property), 0, allProperties.Count - 1);
|
||||
}
|
||||
|
||||
object value = property.GetValue(propertyOwner.First);
|
||||
@@ -2141,7 +2151,8 @@ namespace Barotrauma
|
||||
if (element.GetAttributeBool("flippedx", false)) item.FlipX(false);
|
||||
if (element.GetAttributeBool("flippedy", false)) item.FlipY(false);
|
||||
|
||||
item.condition = element.GetAttributeFloat("condition", item.Prefab.Health);
|
||||
float condition = element.GetAttributeFloat("condition", item.MaxCondition);
|
||||
item.condition = MathHelper.Clamp(condition, 0, item.MaxCondition);
|
||||
item.lastSentCondition = item.condition;
|
||||
|
||||
item.SetActiveSprite();
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using Barotrauma.Items.Components;
|
||||
using Barotrauma.Networking;
|
||||
using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Barotrauma
|
||||
@@ -92,10 +93,10 @@ namespace Barotrauma
|
||||
{
|
||||
if (!Item.ItemList.Contains(container.Item))
|
||||
{
|
||||
string errorMsg = "Attempted to create a network event for an item (" + container.Item.Name + ") that hasn't been fully initialized yet.";
|
||||
string errorMsg = "Attempted to create a network event for an item (" + container.Item.Name + ") that hasn't been fully initialized yet.\n" + Environment.StackTrace;
|
||||
DebugConsole.ThrowError(errorMsg);
|
||||
GameAnalyticsManager.AddErrorEventOnce(
|
||||
"ItemInventory.CreateServerEvent:EventForUninitializedItem" + container.Item.Name + container.Item.ID,
|
||||
"ItemInventory.CreateServerEvent:EventForUninitializedItem" + container.Item.Name + container.Item.ID,
|
||||
GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -12,10 +12,7 @@ namespace Barotrauma
|
||||
{
|
||||
private readonly XElement configElement;
|
||||
private readonly string configPath;
|
||||
|
||||
[Serialize(false, false)]
|
||||
public bool HideInMenus { get; set; }
|
||||
|
||||
|
||||
public List<Pair<MapEntityPrefab, Rectangle>> DisplayEntities
|
||||
{
|
||||
get;
|
||||
|
||||
@@ -409,7 +409,7 @@ namespace Barotrauma
|
||||
public void ServerWrite(IWriteMessage msg, Client c, object[] extraData = null)
|
||||
{
|
||||
LevelObject obj = extraData[0] as LevelObject;
|
||||
msg.WriteRangedIntegerDeprecated(0, objects.Count, objects.IndexOf(obj));
|
||||
msg.WriteRangedInteger(objects.IndexOf(obj), 0, objects.Count);
|
||||
obj.ServerWrite(msg, c);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -344,7 +344,11 @@ namespace Barotrauma
|
||||
structure.Update(deltaTime, cam);
|
||||
}
|
||||
|
||||
foreach (Gap gap in Gap.GapList)
|
||||
//update gaps in random order, because otherwise in rooms with multiple gaps
|
||||
//the water/air will always tend to flow through the first gap in the list,
|
||||
//which may lead to weird behavior like water draining down only through
|
||||
//one gap in a room even if there are several
|
||||
foreach (Gap gap in Gap.GapList.OrderBy(g => Rand.Int(int.MaxValue)))
|
||||
{
|
||||
gap.Update(deltaTime, cam);
|
||||
}
|
||||
@@ -562,7 +566,7 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
[Serialize(1f, true), Editable(0.1f, 10f, DecimalCount = 3, ValueStep = 0.1f)]
|
||||
[Serialize(1f, true), Editable(0.01f, 10f, DecimalCount = 3, ValueStep = 0.1f)]
|
||||
public virtual float Scale { get; set; } = 1;
|
||||
#endregion
|
||||
}
|
||||
|
||||
@@ -77,7 +77,10 @@ namespace Barotrauma
|
||||
get;
|
||||
protected set;
|
||||
}
|
||||
|
||||
|
||||
[Serialize(false, false)]
|
||||
public bool HideInMenus { get; set; }
|
||||
|
||||
[Serialize(false, false)]
|
||||
public bool Linkable
|
||||
{
|
||||
|
||||
@@ -8,6 +8,8 @@ namespace Barotrauma
|
||||
{
|
||||
public class Md5Hash
|
||||
{
|
||||
private static Regex removeWhitespaceRegex = new Regex(@"\s+", RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
||||
|
||||
public string Hash { get; private set; }
|
||||
|
||||
public string ShortHash { get; private set; }
|
||||
@@ -34,14 +36,13 @@ namespace Barotrauma
|
||||
|
||||
public Md5Hash(XDocument doc)
|
||||
{
|
||||
if (doc == null) return;
|
||||
|
||||
string docString = Regex.Replace(doc.ToString(), @"\s+", "");
|
||||
|
||||
if (doc == null) { return; }
|
||||
|
||||
string docString = removeWhitespaceRegex.Replace(doc.ToString(), "");
|
||||
|
||||
byte[] inputBytes = Encoding.ASCII.GetBytes(docString);
|
||||
|
||||
Hash = CalculateHash(inputBytes);
|
||||
|
||||
|
||||
Hash = CalculateHash(inputBytes);
|
||||
ShortHash = GetShortHash(Hash);
|
||||
}
|
||||
|
||||
|
||||
@@ -1296,7 +1296,6 @@ namespace Barotrauma
|
||||
|
||||
public override void Update(float deltaTime, Camera cam)
|
||||
{
|
||||
base.Update(deltaTime, cam);
|
||||
if (aiTarget != null)
|
||||
{
|
||||
aiTarget.SightRange = Submarine == null ? aiTarget.MinSightRange : Submarine.Velocity.Length() / 2 * aiTarget.MaxSightRange;
|
||||
|
||||
@@ -10,6 +10,7 @@ using System.ComponentModel;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml.Linq;
|
||||
using Voronoi2;
|
||||
|
||||
@@ -82,6 +83,7 @@ namespace Barotrauma
|
||||
private static float lastPickedFraction;
|
||||
private static Vector2 lastPickedNormal;
|
||||
|
||||
private Task hashTask;
|
||||
private Md5Hash hash;
|
||||
|
||||
private string filePath;
|
||||
@@ -165,10 +167,12 @@ namespace Barotrauma
|
||||
{
|
||||
get
|
||||
{
|
||||
if (hash != null) return hash;
|
||||
|
||||
XDocument doc = OpenFile(filePath);
|
||||
hash = new Md5Hash(doc);
|
||||
if (hash == null)
|
||||
{
|
||||
XDocument doc = OpenFile(filePath);
|
||||
StartHashDocTask(doc);
|
||||
hashTask.Wait();
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
@@ -316,7 +320,7 @@ namespace Barotrauma
|
||||
DebugConsole.ThrowError("Error loading submarine " + filePath + "!", e);
|
||||
}
|
||||
|
||||
if (hash != "")
|
||||
if (!string.IsNullOrWhiteSpace(hash))
|
||||
{
|
||||
this.hash = new Md5Hash(hash);
|
||||
}
|
||||
@@ -341,6 +345,11 @@ namespace Barotrauma
|
||||
|
||||
if (doc != null && doc.Root != null)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(hash))
|
||||
{
|
||||
StartHashDocTask(doc);
|
||||
}
|
||||
|
||||
displayName = TextManager.Get("Submarine.Name." + name, true);
|
||||
if (displayName == null || displayName.Length == 0) displayName = name;
|
||||
|
||||
@@ -397,6 +406,18 @@ namespace Barotrauma
|
||||
FreeID();
|
||||
}
|
||||
|
||||
public void StartHashDocTask(XDocument doc)
|
||||
{
|
||||
if (hash != null) { return; }
|
||||
if (hashTask != null) { return; }
|
||||
|
||||
hashTask = new Task(() =>
|
||||
{
|
||||
hash = new Md5Hash(doc);
|
||||
});
|
||||
hashTask.Start();
|
||||
}
|
||||
|
||||
public bool HasTag(SubmarineTag tag)
|
||||
{
|
||||
return tags.HasFlag(tag);
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
const string SavePath = "Data/bannedplayers.txt";
|
||||
|
||||
private List<BannedPlayer> bannedPlayers;
|
||||
private readonly List<BannedPlayer> bannedPlayers;
|
||||
|
||||
public IEnumerable<string> BannedNames
|
||||
{
|
||||
|
||||
@@ -233,11 +233,10 @@ namespace Barotrauma.Networking
|
||||
public static bool CanUseRadio(Character sender, out WifiComponent radio)
|
||||
{
|
||||
radio = null;
|
||||
if (sender == null) { return false; }
|
||||
var senderItem = sender.Inventory.Items.FirstOrDefault(i => i?.GetComponent<WifiComponent>() != null);
|
||||
if (senderItem == null) { return false; }
|
||||
radio = senderItem.GetComponent<WifiComponent>();
|
||||
return sender.HasEquippedItem(senderItem) && radio.CanTransmit();
|
||||
if (sender?.Inventory == null || sender.Removed) { return false; }
|
||||
radio = sender.Inventory.Items.FirstOrDefault(i => i?.GetComponent<WifiComponent>() != null)?.GetComponent<WifiComponent>();
|
||||
if (radio?.Item == null) { return false; }
|
||||
return sender.HasEquippedItem(radio.Item) && radio.CanTransmit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,11 +69,12 @@ namespace Barotrauma.Networking
|
||||
|
||||
public static void LoadAll(string file)
|
||||
{
|
||||
if (!File.Exists(file)) return;
|
||||
if (!File.Exists(file)) { return; }
|
||||
|
||||
XDocument doc = XMLExtensions.TryLoadXml(file);
|
||||
if (doc == null || doc.Root == null) return;
|
||||
if (doc == null || doc.Root == null) { return; }
|
||||
|
||||
List.Clear();
|
||||
foreach (XElement element in doc.Root.Elements())
|
||||
{
|
||||
List.Add(new PermissionPreset(element));
|
||||
|
||||
@@ -176,9 +176,7 @@ namespace Barotrauma
|
||||
var spawnedEntity = entitySpawnInfo.Spawn();
|
||||
if (spawnedEntity != null)
|
||||
{
|
||||
#if SERVER
|
||||
CreateNetworkEvent(spawnedEntity, false);
|
||||
#endif
|
||||
CreateNetworkEventProjSpecific(spawnedEntity, false);
|
||||
if (spawnedEntity is Item)
|
||||
{
|
||||
((Item)spawnedEntity).Condition = ((ItemSpawnInfo)entitySpawnInfo).Condition;
|
||||
@@ -189,18 +187,17 @@ namespace Barotrauma
|
||||
while (removeQueue.Count > 0)
|
||||
{
|
||||
var removedEntity = removeQueue.Dequeue();
|
||||
|
||||
#if SERVER
|
||||
if (GameMain.Server != null)
|
||||
if (removedEntity is Item item)
|
||||
{
|
||||
CreateNetworkEvent(removedEntity, true);
|
||||
item.SendPendingNetworkUpdates();
|
||||
}
|
||||
#endif
|
||||
|
||||
CreateNetworkEventProjSpecific(removedEntity, true);
|
||||
removedEntity.Remove();
|
||||
}
|
||||
}
|
||||
|
||||
partial void CreateNetworkEventProjSpecific(Entity entity, bool remove);
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
removeQueue.Clear();
|
||||
|
||||
@@ -15,6 +15,9 @@ namespace Barotrauma
|
||||
|
||||
public Dictionary<string, SerializableProperty> SerializableProperties { get; private set; }
|
||||
|
||||
[Serialize(true, true)]
|
||||
public bool ResetKarmaBetweenRounds { get; set; }
|
||||
|
||||
[Serialize(0.1f, true)]
|
||||
public float KarmaDecay { get; set; }
|
||||
|
||||
@@ -75,13 +78,16 @@ namespace Barotrauma
|
||||
|
||||
[Serialize(1.0f, true)]
|
||||
public float KickBanThreshold { get; set; }
|
||||
|
||||
|
||||
[Serialize(0, true)]
|
||||
public int KicksBeforeBan { get; set; }
|
||||
|
||||
[Serialize(10.0f, true)]
|
||||
public float KarmaNotificationInterval { get; set; }
|
||||
|
||||
[Serialize(120.0f, true)]
|
||||
public float AllowedRetaliationTime { get; set; }
|
||||
|
||||
private readonly AfflictionPrefab herpesAffliction;
|
||||
|
||||
public Dictionary<string, XElement> Presets = new Dictionary<string, XElement>();
|
||||
|
||||
@@ -17,7 +17,6 @@ namespace Barotrauma.Networking
|
||||
void Write(Double val);
|
||||
void WriteVariableUInt32(UInt32 val);
|
||||
void Write(string val);
|
||||
void WriteRangedIntegerDeprecated(int min, int max, int val); //TODO: remove this, val should be first parameter >:(
|
||||
void WriteRangedInteger(int val, int min, int max);
|
||||
void WriteRangedSingle(Single val, Single min, Single max, int bitCount);
|
||||
void Write(byte[] val, int startIndex, int length);
|
||||
|
||||
@@ -493,11 +493,6 @@ namespace Barotrauma.Networking
|
||||
MsgWriter.Write(ref buf, ref seekPos, val);
|
||||
}
|
||||
|
||||
public void WriteRangedIntegerDeprecated(int min, int max, int val)
|
||||
{
|
||||
MsgWriter.WriteRangedInteger(ref buf, ref seekPos, val, min, max);
|
||||
}
|
||||
|
||||
public void WriteRangedInteger(int val, int min, int max)
|
||||
{
|
||||
MsgWriter.WriteRangedInteger(ref buf, ref seekPos, val, min, max);
|
||||
@@ -547,7 +542,7 @@ namespace Barotrauma.Networking
|
||||
if (compressedBuf.Length > outBuf.Length) { Array.Resize(ref outBuf, compressedBuf.Length); }
|
||||
Array.Copy(compressedBuf, outBuf, compressedBuf.Length);
|
||||
length = compressedBuf.Length;
|
||||
DebugConsole.NewMessage("Compressed message: " + LengthBytes + " to " + length);
|
||||
DebugConsole.Log("Compressed message: " + LengthBytes + " to " + length);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -632,7 +627,7 @@ namespace Barotrauma.Networking
|
||||
buf = new byte[decompressedData.Length];
|
||||
Array.Copy(decompressedData, 0, buf, 0, decompressedData.Length);
|
||||
lengthBits = decompressedData.Length * 8;
|
||||
DebugConsole.NewMessage("Decompressing message: " + inLength + " to " + LengthBytes);
|
||||
DebugConsole.Log("Decompressing message: " + inLength + " to " + LengthBytes);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -847,10 +842,6 @@ namespace Barotrauma.Networking
|
||||
MsgWriter.Write(ref buf, ref seekPos, val);
|
||||
}
|
||||
|
||||
public void WriteRangedIntegerDeprecated(int min, int max, int val)
|
||||
{
|
||||
MsgWriter.WriteRangedInteger(ref buf, ref seekPos, val, min, max);
|
||||
}
|
||||
|
||||
public void WriteRangedInteger(int val, int min, int max)
|
||||
{
|
||||
|
||||
+2
@@ -13,6 +13,8 @@ namespace Barotrauma.Networking
|
||||
|
||||
public abstract class NetworkConnection
|
||||
{
|
||||
public const double TimeoutThreshold = 60.0; //full minute for timeout because loading screens can take quite a while
|
||||
|
||||
public string Name;
|
||||
|
||||
public UInt64 SteamID
|
||||
|
||||
+1
-1
@@ -23,7 +23,7 @@ namespace Barotrauma.Networking
|
||||
|
||||
public void Heartbeat()
|
||||
{
|
||||
Timeout = 20.0;
|
||||
Timeout = NetworkConnection.TimeoutThreshold;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Barotrauma.Networking
|
||||
{
|
||||
partial class ServerInfo
|
||||
{
|
||||
public string IP;
|
||||
public string Port;
|
||||
public string ServerName;
|
||||
public string ServerMessage;
|
||||
public bool GameStarted;
|
||||
public int PlayerCount;
|
||||
public int MaxPlayers;
|
||||
public bool HasPassword;
|
||||
|
||||
public bool PingChecked;
|
||||
public int Ping = -1;
|
||||
|
||||
//null value means that the value isn't known (the server may be using
|
||||
//an old version of the game that didn't report these values or the FetchRules query to Steam may not have finished yet)
|
||||
public bool? UsingWhiteList;
|
||||
public SelectionMode? ModeSelectionMode;
|
||||
public SelectionMode? SubSelectionMode;
|
||||
public bool? AllowSpectating;
|
||||
public bool? AllowRespawn;
|
||||
public YesNoMaybe? TraitorsEnabled;
|
||||
public string GameMode;
|
||||
|
||||
public bool? RespondedToSteamQuery = null;
|
||||
|
||||
public string GameVersion;
|
||||
public List<string> ContentPackageNames
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
} = new List<string>();
|
||||
public List<string> ContentPackageHashes
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
} = new List<string>();
|
||||
public List<string> ContentPackageWorkshopUrls
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
} = new List<string>();
|
||||
|
||||
public bool ContentPackagesMatch(IEnumerable<ContentPackage> myContentPackages)
|
||||
{
|
||||
return ContentPackagesMatch(myContentPackages.Select(cp => cp.MD5hash.Hash));
|
||||
}
|
||||
|
||||
public bool ContentPackagesMatch(IEnumerable<string> myContentPackageHashes)
|
||||
{
|
||||
HashSet<string> contentPackageHashes = new HashSet<string>(ContentPackageHashes);
|
||||
return contentPackageHashes.SetEquals(myContentPackageHashes);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -20,7 +20,8 @@ namespace Barotrauma
|
||||
SpeciesName,
|
||||
HasTag,
|
||||
HasStatusTag,
|
||||
Affliction
|
||||
Affliction,
|
||||
EntityType
|
||||
}
|
||||
|
||||
public enum Comparison
|
||||
@@ -161,15 +162,18 @@ namespace Barotrauma
|
||||
{
|
||||
case ConditionType.PropertyValue:
|
||||
SerializableProperty property;
|
||||
if (target?.SerializableProperties == null) { return Operator == OperatorType.NotEquals; }
|
||||
if (target.SerializableProperties.TryGetValue(AttributeName, out property))
|
||||
{
|
||||
return Matches(target, property);
|
||||
}
|
||||
return false;
|
||||
case ConditionType.Name:
|
||||
if (target == null) { return Operator == OperatorType.NotEquals; }
|
||||
return (Operator == OperatorType.Equals) == (target.Name == valStr);
|
||||
case ConditionType.HasTag:
|
||||
{
|
||||
if (target == null) { return Operator == OperatorType.NotEquals; }
|
||||
string[] readTags = valStr.Split(',');
|
||||
int matches = 0;
|
||||
foreach (string tag in readTags)
|
||||
@@ -179,6 +183,8 @@ namespace Barotrauma
|
||||
return Operator == OperatorType.Equals ? matches >= readTags.Length : matches <= 0;
|
||||
}
|
||||
case ConditionType.HasStatusTag:
|
||||
if (target == null) { return Operator == OperatorType.NotEquals; }
|
||||
|
||||
List<DurationListElement> durations = StatusEffect.DurationList.FindAll(d => d.Targets.Contains(target));
|
||||
List<DelayedListElement> delays = DelayedEffect.DelayList.FindAll(d => d.Targets.Contains(target));
|
||||
|
||||
@@ -218,10 +224,29 @@ namespace Barotrauma
|
||||
}
|
||||
return success;
|
||||
case ConditionType.SpeciesName:
|
||||
if (target == null) { return Operator == OperatorType.NotEquals; }
|
||||
Character targetCharacter = target as Character;
|
||||
if (targetCharacter == null) return false;
|
||||
if (targetCharacter == null) { return false; }
|
||||
return (Operator == OperatorType.Equals) == (targetCharacter.SpeciesName == valStr);
|
||||
case ConditionType.EntityType:
|
||||
switch (valStr)
|
||||
{
|
||||
case "character":
|
||||
case "Character":
|
||||
return (Operator == OperatorType.Equals) == target is Character;
|
||||
case "item":
|
||||
case "Item":
|
||||
return (Operator == OperatorType.Equals) == target is Item;
|
||||
case "structure":
|
||||
case "Structure":
|
||||
return (Operator == OperatorType.Equals) == target is Structure;
|
||||
case "null":
|
||||
return (Operator == OperatorType.Equals) == (target == null);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
case ConditionType.Affliction:
|
||||
if (target == null) { return Operator == OperatorType.NotEquals; }
|
||||
if (target is Character targetChar)
|
||||
{
|
||||
var health = targetChar.CharacterHealth;
|
||||
|
||||
@@ -13,6 +13,7 @@ namespace Barotrauma
|
||||
public Entity Entity;
|
||||
public List<ISerializableEntity> Targets;
|
||||
public float Timer;
|
||||
public Character User;
|
||||
}
|
||||
|
||||
partial class StatusEffect
|
||||
@@ -432,7 +433,6 @@ namespace Barotrauma
|
||||
case PropertyConditional.Comparison.Or:
|
||||
foreach (ISerializableEntity target in targets)
|
||||
{
|
||||
if (target == null || target.SerializableProperties == null) { continue; }
|
||||
foreach (PropertyConditional pc in propertyConditionals)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(pc.TargetItemComponentName))
|
||||
@@ -449,7 +449,6 @@ namespace Barotrauma
|
||||
case PropertyConditional.Comparison.And:
|
||||
foreach (ISerializableEntity target in targets)
|
||||
{
|
||||
if (target == null || target.SerializableProperties == null) { continue; }
|
||||
foreach (PropertyConditional pc in propertyConditionals)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(pc.TargetItemComponentName))
|
||||
@@ -516,6 +515,7 @@ namespace Barotrauma
|
||||
if (existingEffect != null)
|
||||
{
|
||||
existingEffect.Timer = Math.Max(existingEffect.Timer, duration);
|
||||
existingEffect.User = user;
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -554,6 +554,7 @@ namespace Barotrauma
|
||||
if (existingEffect != null)
|
||||
{
|
||||
existingEffect.Timer = Math.Max(existingEffect.Timer, duration);
|
||||
existingEffect.User = user;
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -607,7 +608,8 @@ namespace Barotrauma
|
||||
Parent = this,
|
||||
Timer = duration,
|
||||
Entity = entity,
|
||||
Targets = targets
|
||||
Targets = targets,
|
||||
User = user
|
||||
};
|
||||
|
||||
DurationList.Add(element);
|
||||
@@ -641,6 +643,7 @@ namespace Barotrauma
|
||||
|
||||
if (target is Character character)
|
||||
{
|
||||
if (character.Removed) { continue; }
|
||||
character.LastDamageSource = entity;
|
||||
foreach (Limb limb in character.AnimController.Limbs)
|
||||
{
|
||||
@@ -651,6 +654,7 @@ namespace Barotrauma
|
||||
}
|
||||
else if (target is Limb limb)
|
||||
{
|
||||
if (limb.character.Removed) { continue; }
|
||||
limb.character.DamageLimb(entity.WorldPosition, limb, new List<Affliction>() { multipliedAffliction }, stun: 0.0f, playSound: false, attackImpulse: 0.0f, attacker: affliction.Source);
|
||||
}
|
||||
}
|
||||
@@ -669,7 +673,7 @@ namespace Barotrauma
|
||||
targetLimb = limb;
|
||||
targetCharacter = limb.character;
|
||||
}
|
||||
if (targetCharacter != null)
|
||||
if (targetCharacter != null && !targetCharacter.Removed)
|
||||
{
|
||||
float prevVitality = targetCharacter.Vitality;
|
||||
targetCharacter.CharacterHealth.ReduceAffliction(targetLimb, reduceAffliction.First, reduceAmount);
|
||||
@@ -827,11 +831,13 @@ namespace Barotrauma
|
||||
|
||||
if (target is Character character)
|
||||
{
|
||||
character.AddDamage(character.WorldPosition, new List<Affliction>() { multipliedAffliction }, stun: 0.0f, playSound: false);
|
||||
if (character.Removed) { continue; }
|
||||
character.AddDamage(character.WorldPosition, new List<Affliction>() { multipliedAffliction }, stun: 0.0f, playSound: false, attacker: element.User);
|
||||
}
|
||||
else if (target is Limb limb)
|
||||
{
|
||||
limb.character.DamageLimb(limb.WorldPosition, limb, new List<Affliction>() { multipliedAffliction }, stun: 0.0f, playSound: false, attackImpulse: 0.0f);
|
||||
if (limb.character.Removed) { continue; }
|
||||
limb.character.DamageLimb(limb.WorldPosition, limb, new List<Affliction>() { multipliedAffliction }, stun: 0.0f, playSound: false, attackImpulse: 0.0f, attacker: element.User);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -848,12 +854,12 @@ namespace Barotrauma
|
||||
targetLimb = limb;
|
||||
targetCharacter = limb.character;
|
||||
}
|
||||
if (targetCharacter != null)
|
||||
if (targetCharacter != null && !targetCharacter.Removed)
|
||||
{
|
||||
float prevVitality = targetCharacter.Vitality;
|
||||
targetCharacter.CharacterHealth.ReduceAffliction(targetLimb, reduceAffliction.First, reduceAffliction.Second * deltaTime);
|
||||
#if SERVER
|
||||
GameMain.Server.KarmaManager.OnCharacterHealthChanged(targetCharacter, element.Parent.user, prevVitality - targetCharacter.Vitality);
|
||||
GameMain.Server.KarmaManager.OnCharacterHealthChanged(targetCharacter, element.User, prevVitality - targetCharacter.Vitality);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -861,7 +867,7 @@ namespace Barotrauma
|
||||
|
||||
element.Timer -= deltaTime;
|
||||
|
||||
if (element.Timer > 0.0f) continue;
|
||||
if (element.Timer > 0.0f) { continue; }
|
||||
DurationList.Remove(element);
|
||||
}
|
||||
}
|
||||
@@ -873,20 +879,17 @@ namespace Barotrauma
|
||||
CoroutineManager.StopCoroutines("statuseffect");
|
||||
DelayedEffect.DelayList.Clear();
|
||||
DurationList.Clear();
|
||||
#if CLIENT
|
||||
//ActiveLoopingSounds.Clear();
|
||||
#endif
|
||||
}
|
||||
|
||||
public void AddTag(string tag)
|
||||
{
|
||||
if (tags.Contains(tag)) return;
|
||||
if (tags.Contains(tag)) { return; }
|
||||
tags.Add(tag);
|
||||
}
|
||||
|
||||
public bool HasTag(string tag)
|
||||
{
|
||||
if (tag == null) return true;
|
||||
if (tag == null) { return true; }
|
||||
|
||||
return (tags.Contains(tag) || tags.Contains(tag.ToLowerInvariant()));
|
||||
}
|
||||
|
||||
@@ -311,7 +311,16 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
return string.Format(text, args);
|
||||
try
|
||||
{
|
||||
return string.Format(text, args);
|
||||
}
|
||||
catch (FormatException)
|
||||
{
|
||||
string errorMsg = "Failed to format text \"" + text + "\", args: " + string.Join(", ", args);
|
||||
GameAnalyticsManager.AddErrorEventOnce("TextManager.GetFormatted:FormatException", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
||||
return text;
|
||||
}
|
||||
}
|
||||
|
||||
public static string FormatServerMessage(string textId)
|
||||
@@ -621,6 +630,8 @@ namespace Barotrauma
|
||||
|
||||
static Regex isCJK = new Regex(
|
||||
@"\p{IsHangulJamo}|" +
|
||||
@"\p{IsHiragana}|" +
|
||||
@"\p{IsKatakana}|" +
|
||||
@"\p{IsCJKRadicalsSupplement}|" +
|
||||
@"\p{IsCJKSymbolsandPunctuation}|" +
|
||||
@"\p{IsEnclosedCJKLettersandMonths}|" +
|
||||
@@ -635,6 +646,7 @@ namespace Barotrauma
|
||||
/// </summary>
|
||||
public static bool IsCJK(string text)
|
||||
{
|
||||
if (string.IsNullOrEmpty(text)) { return false; }
|
||||
return isCJK.IsMatch(text);
|
||||
}
|
||||
|
||||
|
||||
@@ -427,12 +427,8 @@ namespace Barotrauma
|
||||
FileInfo[] files = dir.GetFiles();
|
||||
foreach (FileInfo file in files)
|
||||
{
|
||||
string temppath = Path.Combine(destDirName, file.Name);
|
||||
if (overwriteExisting && File.Exists(temppath))
|
||||
{
|
||||
File.Delete(temppath);
|
||||
}
|
||||
file.CopyTo(temppath, false);
|
||||
string tempPath = Path.Combine(destDirName, file.Name);
|
||||
file.CopyTo(tempPath, overwriteExisting);
|
||||
}
|
||||
|
||||
// If copying subdirectories, copy them and their contents to new location.
|
||||
@@ -440,8 +436,8 @@ namespace Barotrauma
|
||||
{
|
||||
foreach (DirectoryInfo subdir in dirs)
|
||||
{
|
||||
string temppath = Path.Combine(destDirName, subdir.Name);
|
||||
CopyFolder(subdir.FullName, temppath, copySubDirs);
|
||||
string tempPath = Path.Combine(destDirName, subdir.Name);
|
||||
CopyFolder(subdir.FullName, tempPath, copySubDirs, overwriteExisting);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user