(5a377a8ee) Unstable v0.9.1000.0

This commit is contained in:
Juan Pablo Arce
2020-05-13 12:55:42 -03:00
parent b143329701
commit a1ca41aa5d
426 changed files with 14384 additions and 5708 deletions
@@ -30,9 +30,9 @@ namespace Barotrauma
public float EmpStrength { get; set; }
public Explosion(float range, float force, float damage, float structureDamage, float empStrength = 0.0f)
public Explosion(float range, float force, float damage, float structureDamage, float itemDamage, float empStrength = 0.0f)
{
attack = new Attack(damage, 0.0f, 0.0f, structureDamage, range)
attack = new Attack(damage, 0.0f, 0.0f, structureDamage, itemDamage, range)
{
SeverLimbsProbability = 1.0f
};
@@ -157,42 +157,47 @@ namespace Barotrauma
if (GameMain.NetworkMember == null || !GameMain.NetworkMember.IsClient)
{
if (flames)
foreach (Item item in Item.ItemList)
{
foreach (Item item in Item.ItemList)
if (item.Condition <= 0.0f) { continue; }
if (Vector2.Distance(item.WorldPosition, worldPosition) > attack.Range * 0.5f) { continue; }
if (flames && !item.FireProof)
{
if (item.CurrentHull != hull || item.FireProof || item.Condition <= 0.0f) { continue; }
//don't apply OnFire effects if the item is inside a fireproof container
//(or if it's inside a container that's inside a fireproof container, etc)
Item container = item.Container;
bool fireProof = false;
while (container != null)
{
if (container.FireProof) { fireProof = true; break; }
if (container.FireProof)
{
fireProof = true;
break;
}
container = container.Container;
}
if (fireProof || Vector2.Distance(item.WorldPosition, worldPosition) > attack.Range * 0.5f) { continue; }
item.ApplyStatusEffects(ActionType.OnFire, 1.0f);
if (item.Condition <= 0.0f && GameMain.NetworkMember != null && GameMain.NetworkMember.IsServer)
if (!fireProof)
{
GameMain.NetworkMember.CreateEntityEvent(item, new object[] { NetEntityEvent.Type.ApplyStatusEffect, ActionType.OnFire });
item.ApplyStatusEffects(ActionType.OnFire, 1.0f);
if (item.Condition <= 0.0f && GameMain.NetworkMember != null && GameMain.NetworkMember.IsServer)
{
GameMain.NetworkMember.CreateEntityEvent(item, new object[] { NetEntityEvent.Type.ApplyStatusEffect, ActionType.OnFire });
}
}
}
if (item.Prefab.DamagedByExplosions && !item.Indestructible)
if (item.Prefab.DamagedByExplosions && !item.Indestructible)
{
float limbRadius = item.body == null ? 0.0f : item.body.GetMaxExtent();
float dist = Vector2.Distance(item.WorldPosition, worldPosition);
dist = Math.Max(0.0f, dist - ConvertUnits.ToDisplayUnits(limbRadius));
if (dist > attack.Range)
{
float limbRadius = item.body == null ? 0.0f : item.body.GetMaxExtent();
float dist = Vector2.Distance(item.WorldPosition, worldPosition);
dist = Math.Max(0.0f, dist - ConvertUnits.ToDisplayUnits(limbRadius));
if (dist > attack.Range) { continue; }
float distFactor = 1.0f - dist / attack.Range;
float damageAmount = attack.GetItemDamage(1.0f);
item.Condition -= damageAmount * distFactor;
continue;
}
float distFactor = 1.0f - dist / attack.Range;
float damageAmount = attack.GetItemDamage(1.0f) * item.Prefab.ExplosionDamageMultiplier;
item.Condition -= damageAmount * distFactor;
}
}
}
@@ -200,10 +205,9 @@ namespace Barotrauma
partial void ExplodeProjSpecific(Vector2 worldPosition, Hull hull);
public static void DamageCharacters(Vector2 worldPosition, Attack attack, float force, Entity damageSource, Character attacker)
{
if (attack.Range <= 0.0f) return;
if (attack.Range <= 0.0f) { return; }
//long range for the broad distance check, because large characters may still be in range even if their collider isn't
float broadRange = Math.Max(attack.Range * 10.0f, 10000.0f);
@@ -220,19 +224,20 @@ namespace Barotrauma
Vector2 explosionPos = worldPosition;
if (c.Submarine != null) { explosionPos -= c.Submarine.Position; }
Hull hull = Hull.FindHull(ConvertUnits.ToDisplayUnits(explosionPos), null, false);
Hull hull = Hull.FindHull(explosionPos, null, false);
bool underWater = hull == null || explosionPos.Y < hull.Surface;
explosionPos = ConvertUnits.ToSimUnits(explosionPos);
Dictionary<Limb, float> distFactors = new Dictionary<Limb, float>();
Dictionary<Limb, float> damages = new Dictionary<Limb, float>();
foreach (Limb limb in c.AnimController.Limbs)
{
float dist = Vector2.Distance(limb.WorldPosition, worldPosition);
//calculate distance from the "outer surface" of the physics body
//doesn't take the rotation of the limb into account, but should be accurate enough for this purpose
float limbRadius = Math.Max(Math.Max(limb.body.width * 0.5f, limb.body.height * 0.5f), limb.body.radius);
float limbRadius = limb.body.GetMaxExtent();
dist = Math.Max(0.0f, dist - ConvertUnits.ToDisplayUnits(limbRadius));
if (dist > attack.Range) { continue; }
@@ -240,14 +245,18 @@ namespace Barotrauma
float distFactor = 1.0f - dist / attack.Range;
//solid obstacles between the explosion and the limb reduce the effect of the explosion by 90%
if (Submarine.CheckVisibility(limb.SimPosition, explosionPos) != null) distFactor *= 0.1f;
if (Submarine.CheckVisibility(limb.SimPosition, explosionPos) != null)
{
distFactor *= 0.1f;
}
distFactors.Add(limb, distFactor);
List<Affliction> modifiedAfflictions = new List<Affliction>();
int limbCount = c.AnimController.Limbs.Count(l => !l.IsSevered && !l.ignoreCollisions);
foreach (Affliction affliction in attack.Afflictions.Keys)
{
modifiedAfflictions.Add(affliction.CreateMultiplied(distFactor / c.AnimController.Limbs.Length));
modifiedAfflictions.Add(affliction.CreateMultiplied(distFactor / limbCount));
}
c.LastDamageSource = damageSource;
if (attacker == null)
@@ -255,14 +264,18 @@ namespace Barotrauma
if (damageSource is Item item)
{
attacker = item.GetComponent<Projectile>()?.User;
if (attacker == null) attacker = item.GetComponent<MeleeWeapon>()?.User;
if (attacker == null)
{
attacker = item.GetComponent<MeleeWeapon>()?.User;
}
}
}
//use a position slightly from the limb's position towards the explosion
//ensures that the attack hits the correct limb and that the direction of the hit can be determined correctly in the AddDamage methods
Vector2 hitPos = limb.WorldPosition + (worldPosition - limb.WorldPosition) / dist * 0.01f;
c.AddDamage(hitPos, modifiedAfflictions, attack.Stun * distFactor, false, attacker: attacker);
AttackResult attackResult = c.AddDamage(hitPos, modifiedAfflictions, attack.Stun * distFactor, false, attacker: attacker);
damages.Add(limb, attackResult.Damage);
if (attack.StatusEffects != null && attack.StatusEffects.Any())
{
@@ -287,14 +300,19 @@ namespace Barotrauma
}
//sever joints
if (c.IsDead && attack.SeverLimbsProbability > 0.0f)
if (attack.SeverLimbsProbability > 0.0f)
{
foreach (Limb limb in c.AnimController.Limbs)
{
if (!distFactors.ContainsKey(limb)) { continue; }
if (Rand.Range(0.0f, 1.0f) < attack.SeverLimbsProbability * distFactors[limb])
if (limb.character.Removed || limb.Removed) { continue; }
if (limb.IsSevered) { continue; }
if (!c.IsDead && !limb.CanBeSeveredAlive) { continue; }
if (distFactors.TryGetValue(limb, out float distFactor))
{
c.TrySeverLimbJoints(limb, 1.0f);
if (damages.TryGetValue(limb, out float damage))
{
c.TrySeverLimbJoints(limb, attack.SeverLimbsProbability * distFactor, damage);
}
}
}
}