(d9829ac) v0.9.4.0
This commit is contained in:
@@ -9,6 +9,8 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
using Barotrauma.Networking;
|
||||
using LimbParams = Barotrauma.RagdollParams.LimbParams;
|
||||
using JointParams = Barotrauma.RagdollParams.JointParams;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
@@ -21,14 +23,14 @@ namespace Barotrauma
|
||||
partial class LimbJoint : RevoluteJoint
|
||||
{
|
||||
public bool IsSevered;
|
||||
public bool CanBeSevered => jointParams.CanBeSevered;
|
||||
public readonly JointParams jointParams;
|
||||
public bool CanBeSevered => Params.CanBeSevered;
|
||||
public readonly JointParams Params;
|
||||
public readonly Ragdoll ragdoll;
|
||||
public readonly Limb LimbA, LimbB;
|
||||
|
||||
public LimbJoint(Limb limbA, Limb limbB, JointParams jointParams, Ragdoll ragdoll) : this(limbA, limbB, Vector2.One, Vector2.One)
|
||||
{
|
||||
this.jointParams = jointParams;
|
||||
Params = jointParams;
|
||||
this.ragdoll = ragdoll;
|
||||
LoadParams();
|
||||
}
|
||||
@@ -43,63 +45,37 @@ namespace Barotrauma
|
||||
LimbB = limbB;
|
||||
}
|
||||
|
||||
public void SaveParams()
|
||||
{
|
||||
// Saving to the params is handled only in the params level.
|
||||
return;
|
||||
|
||||
jointParams.Stiffness = MaxMotorTorque;
|
||||
if (ragdoll.IsFlipped)
|
||||
{
|
||||
jointParams.Limb1Anchor = ConvertUnits.ToDisplayUnits(new Vector2(-LocalAnchorA.X, LocalAnchorA.Y) / jointParams.Ragdoll.JointScale);
|
||||
jointParams.Limb2Anchor = ConvertUnits.ToDisplayUnits(new Vector2(-LocalAnchorB.X, LocalAnchorB.Y) / jointParams.Ragdoll.JointScale);
|
||||
jointParams.UpperLimit = MathHelper.ToDegrees(-LowerLimit);
|
||||
jointParams.LowerLimit = MathHelper.ToDegrees(-UpperLimit);
|
||||
}
|
||||
else
|
||||
{
|
||||
jointParams.Limb1Anchor = ConvertUnits.ToDisplayUnits(LocalAnchorA / jointParams.Ragdoll.JointScale);
|
||||
jointParams.Limb2Anchor = ConvertUnits.ToDisplayUnits(LocalAnchorB / jointParams.Ragdoll.JointScale);
|
||||
jointParams.UpperLimit = MathHelper.ToDegrees(UpperLimit);
|
||||
jointParams.LowerLimit = MathHelper.ToDegrees(LowerLimit);
|
||||
}
|
||||
}
|
||||
|
||||
public void LoadParams()
|
||||
{
|
||||
MaxMotorTorque = jointParams.Stiffness;
|
||||
LimitEnabled = jointParams.LimitEnabled;
|
||||
if (float.IsNaN(jointParams.LowerLimit))
|
||||
MaxMotorTorque = Params.Stiffness;
|
||||
LimitEnabled = Params.LimitEnabled;
|
||||
if (float.IsNaN(Params.LowerLimit))
|
||||
{
|
||||
jointParams.LowerLimit = 0;
|
||||
Params.LowerLimit = 0;
|
||||
}
|
||||
if (float.IsNaN(jointParams.UpperLimit))
|
||||
if (float.IsNaN(Params.UpperLimit))
|
||||
{
|
||||
jointParams.UpperLimit = 0;
|
||||
Params.UpperLimit = 0;
|
||||
}
|
||||
if (ragdoll.IsFlipped)
|
||||
{
|
||||
LocalAnchorA = ConvertUnits.ToSimUnits(new Vector2(-jointParams.Limb1Anchor.X, jointParams.Limb1Anchor.Y) * jointParams.Ragdoll.JointScale);
|
||||
LocalAnchorB = ConvertUnits.ToSimUnits(new Vector2(-jointParams.Limb2Anchor.X, jointParams.Limb2Anchor.Y) * jointParams.Ragdoll.JointScale);
|
||||
UpperLimit = MathHelper.ToRadians(-jointParams.LowerLimit);
|
||||
LowerLimit = MathHelper.ToRadians(-jointParams.UpperLimit);
|
||||
LocalAnchorA = ConvertUnits.ToSimUnits(new Vector2(-Params.Limb1Anchor.X, Params.Limb1Anchor.Y) * Params.Ragdoll.JointScale);
|
||||
LocalAnchorB = ConvertUnits.ToSimUnits(new Vector2(-Params.Limb2Anchor.X, Params.Limb2Anchor.Y) * Params.Ragdoll.JointScale);
|
||||
UpperLimit = MathHelper.ToRadians(-Params.LowerLimit);
|
||||
LowerLimit = MathHelper.ToRadians(-Params.UpperLimit);
|
||||
}
|
||||
else
|
||||
{
|
||||
LocalAnchorA = ConvertUnits.ToSimUnits(jointParams.Limb1Anchor * jointParams.Ragdoll.JointScale);
|
||||
LocalAnchorB = ConvertUnits.ToSimUnits(jointParams.Limb2Anchor * jointParams.Ragdoll.JointScale);
|
||||
UpperLimit = MathHelper.ToRadians(jointParams.UpperLimit);
|
||||
LowerLimit = MathHelper.ToRadians(jointParams.LowerLimit);
|
||||
LocalAnchorA = ConvertUnits.ToSimUnits(Params.Limb1Anchor * Params.Ragdoll.JointScale);
|
||||
LocalAnchorB = ConvertUnits.ToSimUnits(Params.Limb2Anchor * Params.Ragdoll.JointScale);
|
||||
UpperLimit = MathHelper.ToRadians(Params.UpperLimit);
|
||||
LowerLimit = MathHelper.ToRadians(Params.LowerLimit);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
partial class Limb : ISerializableEntity, ISpatialEntity
|
||||
{
|
||||
// Note: not used
|
||||
private const float LimbDensity = 15;
|
||||
private const float LimbAngularDamping = 7;
|
||||
|
||||
//how long it takes for severed limbs to fade out
|
||||
private const float SeveredFadeOutTime = 10.0f;
|
||||
|
||||
@@ -108,12 +84,12 @@ namespace Barotrauma
|
||||
/// Note that during the limb initialization, character.AnimController returns null, whereas this field is already assigned.
|
||||
/// </summary>
|
||||
public readonly Ragdoll ragdoll;
|
||||
public readonly LimbParams limbParams;
|
||||
public readonly LimbParams Params;
|
||||
|
||||
//the physics body of the limb
|
||||
public PhysicsBody body;
|
||||
|
||||
public Vector2 StepOffset => ConvertUnits.ToSimUnits(limbParams.StepOffset) * ragdoll.RagdollParams.JointScale;
|
||||
public Vector2 StepOffset => ConvertUnits.ToSimUnits(Params.StepOffset) * ragdoll.RagdollParams.JointScale;
|
||||
|
||||
public bool inWater;
|
||||
|
||||
@@ -125,19 +101,34 @@ namespace Barotrauma
|
||||
|
||||
private bool isSevered;
|
||||
private float severedFadeOutTimer;
|
||||
|
||||
public Vector2? MouthPos;
|
||||
|
||||
private Vector2? mouthPos;
|
||||
public Vector2 MouthPos
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!mouthPos.HasValue)
|
||||
{
|
||||
mouthPos = Params.MouthPos;
|
||||
}
|
||||
return mouthPos.Value;
|
||||
}
|
||||
set
|
||||
{
|
||||
mouthPos = value;
|
||||
}
|
||||
}
|
||||
|
||||
public readonly Attack attack;
|
||||
private List<DamageModifier> damageModifiers;
|
||||
|
||||
private Direction dir;
|
||||
|
||||
public int HealthIndex => limbParams.HealthIndex;
|
||||
public float Scale => limbParams.Ragdoll.LimbScale;
|
||||
public float AttackPriority => limbParams.AttackPriority;
|
||||
public bool DoesFlip => limbParams.Flip;
|
||||
public float SteerForce => limbParams.SteerForce;
|
||||
public int HealthIndex => Params.HealthIndex;
|
||||
public float Scale => Params.Ragdoll.LimbScale;
|
||||
public float AttackPriority => Params.AttackPriority;
|
||||
public bool DoesFlip => Params.Flip;
|
||||
public float SteerForce => Params.SteerForce;
|
||||
|
||||
public Vector2 DebugTargetPos;
|
||||
public Vector2 DebugRefPos;
|
||||
@@ -198,7 +189,7 @@ namespace Barotrauma
|
||||
set { dir = (value == -1.0f) ? Direction.Left : Direction.Right; }
|
||||
}
|
||||
|
||||
public int RefJointIndex => limbParams.RefJoint;
|
||||
public int RefJointIndex => Params.RefJoint;
|
||||
|
||||
private List<WearableSprite> wearingItems;
|
||||
public List<WearableSprite> WearingItems
|
||||
@@ -291,7 +282,7 @@ namespace Barotrauma
|
||||
get { return pullJoint.LocalAnchorA; }
|
||||
}
|
||||
|
||||
public string Name => limbParams.Name;
|
||||
public string Name => Params.Name;
|
||||
|
||||
public Dictionary<string, SerializableProperty> SerializableProperties
|
||||
{
|
||||
@@ -303,7 +294,7 @@ namespace Barotrauma
|
||||
{
|
||||
this.ragdoll = ragdoll;
|
||||
this.character = character;
|
||||
this.limbParams = limbParams;
|
||||
this.Params = limbParams;
|
||||
wearingItems = new List<WearableSprite>();
|
||||
dir = Direction.Right;
|
||||
body = new PhysicsBody(limbParams);
|
||||
@@ -324,19 +315,16 @@ namespace Barotrauma
|
||||
pullJoint = new FixedMouseJoint(body.FarseerBody, ConvertUnits.ToSimUnits(limbParams.PullPos * Scale))
|
||||
{
|
||||
Enabled = false,
|
||||
MaxForce = ((type == LimbType.LeftHand || type == LimbType.RightHand) ? 400.0f : 150.0f) * body.Mass
|
||||
//MaxForce = ((type == LimbType.LeftHand || type == LimbType.RightHand) ? 400.0f : 150.0f) * body.Mass
|
||||
// 150 or even 400 is too low if the joint is used for moving the character position from the mainlimb towards the collider position
|
||||
MaxForce = 1000 * Mass
|
||||
};
|
||||
|
||||
GameMain.World.AddJoint(pullJoint);
|
||||
|
||||
var element = limbParams.Element;
|
||||
if (element.Attribute("mouthpos") != null)
|
||||
{
|
||||
MouthPos = ConvertUnits.ToSimUnits(element.GetAttributeVector2("mouthpos", Vector2.Zero));
|
||||
}
|
||||
|
||||
body.BodyType = BodyType.Dynamic;
|
||||
body.FarseerBody.AngularDamping = LimbAngularDamping;
|
||||
|
||||
damageModifiers = new List<DamageModifier>();
|
||||
|
||||
@@ -403,19 +391,19 @@ namespace Barotrauma
|
||||
return AddDamage(simPosition, afflictions, playSound);
|
||||
}
|
||||
|
||||
public AttackResult AddDamage(Vector2 simPosition, List<Affliction> afflictions, bool playSound)
|
||||
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
|
||||
afflictions = new List<Affliction>(afflictions.Where(a => Rand.Range(0.0f, 1.0f) <= a.ApplyProbability));
|
||||
for (int i = 0; i < afflictions.Count; i++)
|
||||
var afflictionsCopy = afflictions.Where(a => Rand.Range(0.0f, 1.0f) <= a.Probability).ToList();
|
||||
for (int i = 0; i < afflictionsCopy.Count; i++)
|
||||
{
|
||||
foreach (DamageModifier damageModifier in damageModifiers)
|
||||
{
|
||||
if (!damageModifier.MatchesAffliction(afflictions[i])) continue;
|
||||
if (SectorHit(damageModifier.ArmorSector, simPosition))
|
||||
if (!damageModifier.MatchesAffliction(afflictionsCopy[i])) continue;
|
||||
if (SectorHit(damageModifier.ArmorSectorInRadians, simPosition))
|
||||
{
|
||||
afflictions[i] = afflictions[i].CreateMultiplied(damageModifier.DamageMultiplier);
|
||||
afflictionsCopy[i] = afflictionsCopy[i].CreateMultiplied(damageModifier.DamageMultiplier);
|
||||
appliedDamageModifiers.Add(damageModifier);
|
||||
}
|
||||
}
|
||||
@@ -424,19 +412,19 @@ namespace Barotrauma
|
||||
{
|
||||
foreach (DamageModifier damageModifier in wearable.WearableComponent.DamageModifiers)
|
||||
{
|
||||
if (!damageModifier.MatchesAffliction(afflictions[i])) continue;
|
||||
if (SectorHit(damageModifier.ArmorSector, simPosition))
|
||||
if (!damageModifier.MatchesAffliction(afflictionsCopy[i])) continue;
|
||||
if (SectorHit(damageModifier.ArmorSectorInRadians, simPosition))
|
||||
{
|
||||
afflictions[i] = afflictions[i].CreateMultiplied(damageModifier.DamageMultiplier);
|
||||
afflictionsCopy[i] = afflictionsCopy[i].CreateMultiplied(damageModifier.DamageMultiplier);
|
||||
appliedDamageModifiers.Add(damageModifier);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AddDamageProjSpecific(simPosition, afflictions, playSound, appliedDamageModifiers);
|
||||
AddDamageProjSpecific(simPosition, afflictionsCopy, playSound, appliedDamageModifiers);
|
||||
|
||||
return new AttackResult(afflictions, this, appliedDamageModifiers);
|
||||
return new AttackResult(afflictionsCopy, this, appliedDamageModifiers);
|
||||
}
|
||||
|
||||
partial void AddDamageProjSpecific(Vector2 simPosition, List<Affliction> afflictions, bool playSound, List<DamageModifier> appliedDamageModifiers);
|
||||
@@ -456,7 +444,7 @@ namespace Barotrauma
|
||||
protected float GetArmorSectorRotationOffset(Vector2 armorSector)
|
||||
{
|
||||
float midAngle = MathUtils.GetMidAngle(armorSector.X, armorSector.Y);
|
||||
float spritesheetOrientation = MathHelper.ToRadians(limbParams.Ragdoll.SpritesheetOrientation);
|
||||
float spritesheetOrientation = Params.GetSpriteOrientation();
|
||||
return midAngle + spritesheetOrientation;
|
||||
}
|
||||
|
||||
@@ -495,10 +483,13 @@ namespace Barotrauma
|
||||
|
||||
partial void UpdateProjSpecific(float deltaTime);
|
||||
|
||||
|
||||
private readonly List<Body> contactBodies = new List<Body>();
|
||||
private List<Body> ignoredBodies;
|
||||
/// <summary>
|
||||
/// Returns true if the attack successfully hit something. If the distance is not given, it will be calculated.
|
||||
/// </summary>
|
||||
public bool UpdateAttack(float deltaTime, Vector2 attackSimPos, IDamageable damageTarget, out AttackResult attackResult, float distance = -1)
|
||||
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));
|
||||
@@ -514,8 +505,11 @@ namespace Barotrauma
|
||||
case HitDetection.Distance:
|
||||
if (dist < attack.DamageRange)
|
||||
{
|
||||
List<Body> ignoredBodies = character.AnimController.Limbs.Select(l => l.body.FarseerBody).ToList();
|
||||
ignoredBodies.Add(character.AnimController.Collider.FarseerBody);
|
||||
if (ignoredBodies == null)
|
||||
{
|
||||
ignoredBodies = character.AnimController.Limbs.Select(l => l.body.FarseerBody).ToList();
|
||||
ignoredBodies.Add(character.AnimController.Collider.FarseerBody);
|
||||
}
|
||||
|
||||
structureBody = Submarine.PickBody(
|
||||
SimPosition, attackSimPos,
|
||||
@@ -541,46 +535,42 @@ namespace Barotrauma
|
||||
}
|
||||
break;
|
||||
case HitDetection.Contact:
|
||||
var targetBodies = new List<Body>();
|
||||
contactBodies.Clear();
|
||||
if (damageTarget is Character targetCharacter)
|
||||
{
|
||||
foreach (Limb limb in targetCharacter.AnimController.Limbs)
|
||||
{
|
||||
if (!limb.IsSevered && limb.body?.FarseerBody != null) targetBodies.Add(limb.body.FarseerBody);
|
||||
if (!limb.IsSevered && limb.body?.FarseerBody != null) contactBodies.Add(limb.body.FarseerBody);
|
||||
}
|
||||
}
|
||||
else if (damageTarget is Structure targetStructure)
|
||||
{
|
||||
if (character.Submarine == null && targetStructure.Submarine != null)
|
||||
{
|
||||
targetBodies.Add(targetStructure.Submarine.PhysicsBody.FarseerBody);
|
||||
contactBodies.Add(targetStructure.Submarine.PhysicsBody.FarseerBody);
|
||||
}
|
||||
else
|
||||
{
|
||||
targetBodies.AddRange(targetStructure.Bodies);
|
||||
contactBodies.AddRange(targetStructure.Bodies);
|
||||
}
|
||||
}
|
||||
else if (damageTarget is Item)
|
||||
{
|
||||
Item targetItem = damageTarget as Item;
|
||||
if (targetItem.body?.FarseerBody != null) targetBodies.Add(targetItem.body.FarseerBody);
|
||||
if (targetItem.body?.FarseerBody != null) contactBodies.Add(targetItem.body.FarseerBody);
|
||||
}
|
||||
|
||||
if (targetBodies != null)
|
||||
ContactEdge contactEdge = body.FarseerBody.ContactList;
|
||||
while (contactEdge != null)
|
||||
{
|
||||
ContactEdge contactEdge = body.FarseerBody.ContactList;
|
||||
while (contactEdge != null)
|
||||
if (contactEdge.Contact != null &&
|
||||
contactEdge.Contact.IsTouching &&
|
||||
contactBodies.Any(b => b == contactEdge.Contact.FixtureA?.Body || b == contactEdge.Contact.FixtureB?.Body))
|
||||
{
|
||||
if (contactEdge.Contact != null &&
|
||||
contactEdge.Contact.IsTouching &&
|
||||
targetBodies.Any(b => b == contactEdge.Contact.FixtureA?.Body || b == contactEdge.Contact.FixtureB?.Body))
|
||||
{
|
||||
structureBody = targetBodies.LastOrDefault();
|
||||
wasHit = true;
|
||||
break;
|
||||
}
|
||||
contactEdge = contactEdge.Next;
|
||||
structureBody = contactBodies.LastOrDefault();
|
||||
wasHit = true;
|
||||
break;
|
||||
}
|
||||
contactEdge = contactEdge.Next;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -601,11 +591,18 @@ namespace Barotrauma
|
||||
LastAttackSoundTime = SoundInterval;
|
||||
}
|
||||
#endif
|
||||
attackResult = attack.DoDamage(character, damageTarget, WorldPosition, 1.0f, playSound);
|
||||
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(MathHelper.ToRadians(ragdoll.RagdollParams.SpritesheetOrientation));
|
||||
var localFront = body.GetLocalFront(Params.GetSpriteOrientation());
|
||||
var from = body.FarseerBody.GetWorldPoint(localFront);
|
||||
var to = from;
|
||||
var drawPos = body.DrawPosition;
|
||||
@@ -665,7 +662,7 @@ namespace Barotrauma
|
||||
{
|
||||
PhysicsBody mainLimbBody = ragdoll.MainLimb.body;
|
||||
Body colliderBody = ragdoll.Collider.FarseerBody;
|
||||
Vector2 mainLimbLocalFront = mainLimbBody.GetLocalFront(MathHelper.ToRadians(ragdoll.RagdollParams.SpritesheetOrientation));
|
||||
Vector2 mainLimbLocalFront = mainLimbBody.GetLocalFront(ragdoll.MainLimb.Params.GetSpriteOrientation());
|
||||
if (Dir < 0)
|
||||
{
|
||||
mainLimbLocalFront.X = -mainLimbLocalFront.X;
|
||||
@@ -715,8 +712,7 @@ namespace Barotrauma
|
||||
|
||||
public void LoadParams()
|
||||
{
|
||||
attack?.Deserialize();
|
||||
pullJoint.LocalAnchorA = ConvertUnits.ToSimUnits(limbParams.PullPos * Scale);
|
||||
pullJoint.LocalAnchorA = ConvertUnits.ToSimUnits(Params.PullPos * Scale);
|
||||
LoadParamsProjSpecific();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user