(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
@@ -166,10 +166,20 @@ namespace Barotrauma
if (isSevered)
{
ragdoll.SubtractMass(this);
if (type == LimbType.Head)
{
character.Kill(CauseOfDeathType.Unknown, null);
}
}
else
{
severedFadeOutTimer = 0.0f;
}
if (!isSevered) severedFadeOutTimer = 0.0f;
#if CLIENT
if (isSevered) damageOverlayStrength = 100.0f;
if (isSevered)
{
damageOverlayStrength = 100.0f;
}
#endif
}
}
@@ -366,12 +376,42 @@ namespace Barotrauma
public string Name => Params.Name;
// Exposed for status effects
public bool IsDead => character.IsDead;
public bool CanBeSeveredAlive
{
get
{
if (character.IsHumanoid) { return false; }
if (this == character.AnimController.MainLimb) { return false; }
if (character.AnimController.CanWalk)
{
switch (type)
{
case LimbType.LeftFoot:
case LimbType.RightFoot:
case LimbType.LeftLeg:
case LimbType.RightLeg:
case LimbType.LeftThigh:
case LimbType.RightThigh:
case LimbType.Legs:
case LimbType.Waist:
return false;
}
}
return true;
}
}
public Dictionary<string, SerializableProperty> SerializableProperties
{
get;
private set;
}
private readonly List<StatusEffect> statusEffects = new List<StatusEffect>();
public Limb(Ragdoll ragdoll, Character character, LimbParams limbParams)
{
this.ragdoll = ragdoll;
@@ -434,6 +474,9 @@ namespace Barotrauma
case "damagemodifier":
DamageModifiers.Add(new DamageModifier(subElement, character.Name));
break;
case "statuseffect":
statusEffects.Add(StatusEffect.Load(subElement, Name));
break;
}
}
@@ -471,43 +514,60 @@ namespace Barotrauma
return AddDamage(simPosition, afflictions, playSound);
}
private readonly List<DamageModifier> appliedDamageModifiers = new List<DamageModifier>();
private readonly List<Affliction> afflictionsCopy = new List<Affliction>();
public AttackResult AddDamage(Vector2 simPosition, IEnumerable<Affliction> afflictions, bool playSound)
{
List<DamageModifier> appliedDamageModifiers = new List<DamageModifier>();
//create a copy of the original affliction list to prevent modifying the afflictions of an Attack/StatusEffect etc
var afflictionsCopy = afflictions.Where(a => Rand.Range(0.0f, 1.0f) <= a.Probability).ToList();
for (int i = 0; i < afflictionsCopy.Count; i++)
appliedDamageModifiers.Clear();
afflictionsCopy.Clear();
foreach (var affliction in afflictions)
{
var newAffliction = affliction;
float random = Rand.Value(Rand.RandSync.Unsynced);
if (random > affliction.Probability) { continue; }
bool applyAffliction = true;
foreach (DamageModifier damageModifier in DamageModifiers)
{
if (!damageModifier.MatchesAffliction(afflictionsCopy[i])) continue;
if (!damageModifier.MatchesAffliction(affliction)) { continue; }
if (random > affliction.Probability * damageModifier.ProbabilityMultiplier)
{
applyAffliction = false;
continue;
}
if (SectorHit(damageModifier.ArmorSectorInRadians, simPosition))
{
afflictionsCopy[i] = afflictionsCopy[i].CreateMultiplied(damageModifier.DamageMultiplier);
newAffliction = affliction.CreateMultiplied(damageModifier.DamageMultiplier);
appliedDamageModifiers.Add(damageModifier);
}
}
foreach (WearableSprite wearable in wearingItems)
{
foreach (DamageModifier damageModifier in wearable.WearableComponent.DamageModifiers)
{
if (!damageModifier.MatchesAffliction(afflictionsCopy[i])) continue;
if (!damageModifier.MatchesAffliction(affliction)) { continue; }
if (random > affliction.Probability * damageModifier.ProbabilityMultiplier)
{
applyAffliction = false;
continue;
}
if (SectorHit(damageModifier.ArmorSectorInRadians, simPosition))
{
afflictionsCopy[i] = afflictionsCopy[i].CreateMultiplied(damageModifier.DamageMultiplier);
newAffliction = affliction.CreateMultiplied(damageModifier.DamageMultiplier);
appliedDamageModifiers.Add(damageModifier);
}
}
}
if (applyAffliction)
{
afflictionsCopy.Add(newAffliction);
}
}
AddDamageProjSpecific(simPosition, afflictionsCopy, playSound, appliedDamageModifiers);
return new AttackResult(afflictionsCopy, this, appliedDamageModifiers);
var result = new AttackResult(afflictionsCopy, this, appliedDamageModifiers);
AddDamageProjSpecific(playSound, result);
return result;
}
partial void AddDamageProjSpecific(Vector2 simPosition, List<Affliction> afflictions, bool playSound, List<DamageModifier> appliedDamageModifiers);
partial void AddDamageProjSpecific(bool playSound, AttackResult result);
public bool SectorHit(Vector2 armorSector, Vector2 simPosition)
{
@@ -564,7 +624,8 @@ namespace Barotrauma
public bool UpdateAttack(float deltaTime, Vector2 attackSimPos, IDamageable damageTarget, out AttackResult attackResult, float distance = -1, Limb targetLimb = null)
{
attackResult = default(AttackResult);
float dist = distance > -1 ? distance : ConvertUnits.ToDisplayUnits(Vector2.Distance(SimPosition, attackSimPos));
Vector2 simPos = ragdoll.SimplePhysicsEnabled ? character.SimPosition : SimPosition;
float dist = distance > -1 ? distance : ConvertUnits.ToDisplayUnits(Vector2.Distance(simPos, attackSimPos));
bool wasRunning = attack.IsRunning;
attack.UpdateAttackTimer(deltaTime);
@@ -577,7 +638,7 @@ namespace Barotrauma
case HitDetection.Distance:
if (dist < attack.DamageRange)
{
structureBody = Submarine.PickBody(SimPosition, attackSimPos, collisionCategory: Physics.CollisionWall | Physics.CollisionLevel, allowInsideFixture: true);
structureBody = Submarine.PickBody(simPos, attackSimPos, collisionCategory: Physics.CollisionWall | Physics.CollisionLevel, allowInsideFixture: true);
if (damageTarget is Item i && i.GetComponent<Items.Components.Door>() != null)
{
// If the attack is aimed to an item and hits an item, it's successful.
@@ -646,33 +707,19 @@ namespace Barotrauma
if (wasHit)
{
bool playSound = false;
#if CLIENT
playSound = LastAttackSoundTime < Timing.TotalTime - SoundInterval;
if (playSound)
if (character == Character.Controlled || GameMain.NetworkMember == null || !GameMain.NetworkMember.IsClient)
{
LastAttackSoundTime = SoundInterval;
ExecuteAttack(damageTarget, targetLimb, out attackResult);
}
#if SERVER
GameMain.NetworkMember.CreateEntityEvent(character, new object[]
{
NetEntityEvent.Type.ExecuteAttack,
this,
(damageTarget as Entity)?.ID ?? Entity.NullEntityID,
damageTarget is Character && targetLimb != null ? Array.IndexOf(((Character)damageTarget).AnimController.Limbs, targetLimb) : 0
});
#endif
if (damageTarget is Character targetCharacter && targetLimb != null)
{
attackResult = attack.DoDamageToLimb(character, targetLimb, WorldPosition, 1.0f, playSound);
}
else
{
attackResult = attack.DoDamage(character, damageTarget, WorldPosition, 1.0f, playSound);
}
if (structureBody != null && attack.StickChance > Rand.Range(0.0f, 1.0f, Rand.RandSync.Server))
{
// TODO: use the hit pos?
var localFront = body.GetLocalFront(Params.GetSpriteOrientation());
var from = body.FarseerBody.GetWorldPoint(localFront);
var to = from;
var drawPos = body.DrawPosition;
StickTo(structureBody, from, to);
}
attack.ResetAttackTimer();
attack.SetCoolDown();
}
Vector2 diff = attackSimPos - SimPosition;
@@ -685,6 +732,7 @@ namespace Barotrauma
{
if (limbIndex < 0 || limbIndex >= character.AnimController.Limbs.Length) { continue; }
Limb limb = character.AnimController.Limbs[limbIndex];
if (limb.IsSevered) { continue; }
diff = attackSimPos - limb.SimPosition;
if (diff == Vector2.Zero) { continue; }
limb.body.ApplyTorque(limb.Mass * character.AnimController.Dir * attack.Torque * limb.Params.AttackForceMultiplier);
@@ -705,11 +753,49 @@ namespace Barotrauma
if (!attack.IsRunning)
{
// Set the main collider where the body lands after the attack
character.AnimController.Collider.SetTransform(character.AnimController.MainLimb.body.SimPosition, rotation: 0);
character.AnimController.Collider.SetTransform(character.AnimController.MainLimb.body.SimPosition, rotation: character.AnimController.Collider.Rotation);
}
return wasHit;
}
public void ExecuteAttack(IDamageable damageTarget, Limb targetLimb, out AttackResult attackResult)
{
bool playSound = false;
#if CLIENT
playSound = LastAttackSoundTime < Timing.TotalTime - SoundInterval;
if (playSound)
{
LastAttackSoundTime = SoundInterval;
}
#endif
if (damageTarget is Character targetCharacter && targetLimb != null)
{
attackResult = attack.DoDamageToLimb(character, targetLimb, WorldPosition, 1.0f, playSound);
}
else
{
if (damageTarget is Item targetItem && !targetItem.Prefab.DamagedByMonsters)
{
attackResult = new AttackResult();
}
else
{
attackResult = attack.DoDamage(character, damageTarget, WorldPosition, 1.0f, playSound);
}
}
/*if (structureBody != null && attack.StickChance > Rand.Range(0.0f, 1.0f, Rand.RandSync.Server))
{
// TODO: use the hit pos?
var localFront = body.GetLocalFront(Params.GetSpriteOrientation());
var from = body.FarseerBody.GetWorldPoint(localFront);
var to = from;
var drawPos = body.DrawPosition;
StickTo(structureBody, from, to);
}*/
attack.ResetAttackTimer();
attack.SetCoolDown();
}
private WeldJoint attachJoint;
private WeldJoint colliderJoint;
public bool IsStuck => attachJoint != null;
@@ -769,6 +855,30 @@ namespace Barotrauma
}
}
private readonly List<ISerializableEntity> targets = new List<ISerializableEntity>();
public void ApplyStatusEffects(ActionType actionType, float deltaTime)
{
foreach (StatusEffect statusEffect in statusEffects)
{
if (statusEffect.type != actionType) { continue; }
if (statusEffect.HasTargetType(StatusEffect.TargetType.NearbyItems) ||
statusEffect.HasTargetType(StatusEffect.TargetType.NearbyCharacters))
{
targets.Clear();
statusEffect.GetNearbyTargets(WorldPosition, targets);
statusEffect.Apply(ActionType.OnActive, deltaTime, character, targets);
}
else
{
if (statusEffect.HasTargetType(StatusEffect.TargetType.Character))
{
statusEffect.Apply(actionType, deltaTime, character, character, WorldPosition);
}
statusEffect.Apply(actionType, deltaTime, character, this, WorldPosition);
}
}
}
public void Remove()
{
body?.Remove();