Barotrauma/BarotraumaShared/Source/Items/Components/ItemComponent.cs
This commit is contained in:
juanjp600
2017-12-20 19:46:53 -03:00
75 changed files with 2109 additions and 596 deletions
@@ -9,6 +9,8 @@ namespace Barotrauma
public enum Animation { None, Climbing, UsingConstruction, Struggle, CPR };
public Animation Anim;
public LimbType GrabLimb;
protected Character character;
protected float walkSpeed, swimSpeed;
@@ -20,6 +20,7 @@ namespace Barotrauma
private float thighTorque;
private float cprAnimState;
private float cprPump;
private float inWaterTimer;
private bool swimming;
@@ -872,7 +873,34 @@ namespace Barotrauma
character.SelectedConstruction = null;
IgnorePlatforms = false;
}
else if (character.SelectedCharacter != null && !character.SelectedCharacter.AllowInput)
{
Limb targetLeftHand = character.SelectedCharacter.AnimController.GetLimb(LimbType.LeftHand);
Limb targetRightHand = character.SelectedCharacter.AnimController.GetLimb(LimbType.RightHand);
Limb targetTorso = character.SelectedCharacter.AnimController.GetLimb(LimbType.Torso);
if (character.SelectedCharacter.AnimController.Dir != Dir)
character.SelectedCharacter.AnimController.Flip();
targetTorso.pullJoint.Enabled = true;
targetTorso.pullJoint.WorldAnchorB = torso.SimPosition + (Vector2.UnitX * -Dir) * 0.2f;
targetTorso.pullJoint.MaxForce = 5000.0f;
if (!targetLeftHand.IsSevered)
{
targetLeftHand.pullJoint.Enabled = true;
targetLeftHand.pullJoint.WorldAnchorB = torso.SimPosition + (new Vector2(1 * Dir, 1)) * 0.2f;
targetLeftHand.pullJoint.MaxForce = 5000.0f;
}
if (!targetRightHand.IsSevered)
{
targetRightHand.pullJoint.Enabled = true;
targetRightHand.pullJoint.WorldAnchorB = torso.SimPosition + (new Vector2(1 * Dir, 1)) * 0.2f;
targetRightHand.pullJoint.MaxForce = 5000.0f;
}
character.SelectedCharacter.AnimController.IgnorePlatforms = true;
}
}
private void UpdateCPR(float deltaTime)
@@ -883,11 +911,16 @@ namespace Barotrauma
return;
}
Character target = character.SelectedCharacter;
Crouching = true;
Vector2 diff = character.SelectedCharacter.SimPosition - character.SimPosition;
var targetHead = character.SelectedCharacter.AnimController.GetLimb(LimbType.Head);
Vector2 diff = target.SimPosition - character.SimPosition;
Limb targetHead = target.AnimController.GetLimb(LimbType.Head);
Limb targetTorso = target.AnimController.GetLimb(LimbType.Torso);
Limb head = GetLimb(LimbType.Head);
Limb torso = GetLimb(LimbType.Torso);
Vector2 headDiff = targetHead == null ? diff : targetHead.SimPosition - character.SimPosition;
targetMovement = new Vector2(diff.X, 0.0f);
@@ -895,21 +928,98 @@ namespace Barotrauma
UpdateStanding();
Vector2 handPos = character.SelectedCharacter.AnimController.GetLimb(LimbType.Torso).SimPosition + Vector2.UnitY * 0.2f;
Vector2 handPos = targetTorso.SimPosition + Vector2.UnitY * 0.2f;
Grab(handPos, handPos);
float yPos = (float)Math.Sin(cprAnimState) * 0.1f;
cprAnimState += deltaTime * 8.0f;
Vector2 colliderPos = GetColliderBottom();
var head = GetLimb(LimbType.Head);
head.pullJoint.WorldAnchorB = new Vector2(targetHead.SimPosition.X, targetHead.SimPosition.Y + 0.6f + yPos);
head.pullJoint.Enabled = true;
if (GameMain.Client == null) //Serverside code
{
if (target.Bleeding <= 0.5f && target.Oxygen <= 0.0f) //If they're bleeding too hard CPR will hurt them
{
target.Oxygen += deltaTime * 0.5f; //Stabilize them
}
}
int skill = character.GetSkillLevel("Medical");
if (cprAnimState % 17 > 15.0f)
{
float yPos = (float)Math.Sin(cprAnimState) * 0.2f;
head.pullJoint.WorldAnchorB = new Vector2(targetHead.SimPosition.X, targetHead.SimPosition.Y + 0.3f + yPos);
head.pullJoint.Enabled = true;
torso.pullJoint.WorldAnchorB = new Vector2(torso.SimPosition.X, colliderPos.Y + (TorsoPosition - 0.2f));
torso.pullJoint.Enabled = true;
if (GameMain.Client == null) //Serverside code
{
float cpr = skill / 2.0f; //Max possible oxygen addition is 20 per second
character.Oxygen -= (30.0f - cpr) * deltaTime; //Worse skill = more oxygen required
if (character.Oxygen > 0.0f) //we didn't suffocate yet did we
target.Oxygen += cpr * deltaTime;
//DebugConsole.NewMessage("CPR Us: " + character.Oxygen + " Them: " + target.Oxygen + " How good we are: restore " + cpr + " use " + (30.0f - cpr), Color.Aqua);
}
}
else
{
head.pullJoint.WorldAnchorB = new Vector2(targetHead.SimPosition.X, targetHead.SimPosition.Y + 0.8f);
head.pullJoint.Enabled = true;
torso.pullJoint.WorldAnchorB = new Vector2(torso.SimPosition.X, colliderPos.Y + (TorsoPosition - 0.1f));
torso.pullJoint.Enabled = true;
if (cprPump >= 1)
{
torso.body.ApplyForce(new Vector2(0, -1000f));
targetTorso.body.ApplyForce(new Vector2(0, -1000f));
cprPump = 0;
if (target.Bleeding <= 0.5f && target.Health <= 0.0f && !target.IsDead) //Have a chance to revive them to 2 HP if they were damaged.
{
if (GameMain.Client == null) //Serverside code
{
float reviveChance = (cprAnimState % 17) * (skill / 50.0f); //~5% max chance for 10 skill, ~50% max chance for 100 skill
float rng = Rand.Int(100, Rand.RandSync.Server);
//DebugConsole.NewMessage("CPR Pump cprAnimState: " + (cprAnimState % 17) + " revive chance: " + reviveChance + " rng: " + rng, Color.Aqua);
if (rng <= reviveChance) //HOLY CRAP YOU SAVED HIM!!!
{
target.Oxygen = Math.Max(target.Oxygen, 10.0f);
target.Health = 2.0f;
Anim = Animation.None;
return;
}
}
}
else if (target.Bleeding > 0.5f || skill < 50) //We will hurt them if they're bleeding or we suck
{
//If not bleeding: 10% skill causes 0.8 damage per pump, 40% skill causes only 0.2
if (target.Bleeding <= 0.5f)
target.AddDamage(CauseOfDeath.Damage, (50 - skill) * 0.02f, character);
else //If bleeding: 2 HP damage per pump. Basically speeds up their death. Don't pump bleeding people!
{
target.AddDamage(CauseOfDeath.Bloodloss, 1.0f, character);
#if CLIENT
SoundPlayer.PlayDamageSound(DamageSoundType.LimbBlunt, 25.0f, targetTorso.body);
for (int i = 0; i < 4; i++)
{
var blood = GameMain.ParticleManager.CreateParticle(inWater ? "waterblood" : "blood", targetTorso.WorldPosition, Rand.Vector(10.0f), 0.0f, target.AnimController.CurrentHull);
}
#endif
}
}
}
cprPump += deltaTime;
}
cprAnimState += deltaTime;
}
public override void DragCharacter(Character target)
{
if (target == null) return;
Limb torso = GetLimb(LimbType.Torso);
Limb leftHand = GetLimb(LimbType.LeftHand);
Limb rightHand = GetLimb(LimbType.RightHand);
@@ -922,31 +1032,34 @@ namespace Barotrauma
for (int i = 0; i < 2; i++)
{
Limb targetLimb = target.AnimController.GetLimb(LimbType.Torso);
Limb targetLimb = target.AnimController.GetLimb(GrabLimb);
if (i == 0)
if (targetLimb == null || targetLimb.IsSevered)
{
if (!targetLeftHand.IsSevered)
targetLimb = target.AnimController.GetLimb(LimbType.Torso);
if (i == 0)
{
targetLimb = targetLeftHand;
if (!targetLeftHand.IsSevered)
{
targetLimb = targetLeftHand;
}
else if (!targetRightHand.IsSevered)
{
targetLimb = targetRightHand;
}
}
else if (!targetRightHand.IsSevered)
else
{
targetLimb = targetRightHand;
if (!targetRightHand.IsSevered)
{
targetLimb = targetRightHand;
}
else if (!targetLeftHand.IsSevered)
{
targetLimb = targetLeftHand;
}
}
}
else
{
if (!targetRightHand.IsSevered)
{
targetLimb = targetRightHand;
}
else if (!targetLeftHand.IsSevered)
{
targetLimb = targetLeftHand;
}
}
Limb pullLimb = i == 0 ? leftHand : rightHand;
if (i == 1 && inWater)
@@ -958,12 +1071,32 @@ namespace Barotrauma
Vector2 diff = ConvertUnits.ToSimUnits(targetLimb.WorldPosition - pullLimb.WorldPosition);
pullLimb.pullJoint.Enabled = true;
pullLimb.pullJoint.WorldAnchorB = pullLimb.SimPosition + diff;
pullLimb.pullJoint.MaxForce = 10000.0f;
if (targetLimb.type == LimbType.Torso)
{
pullLimb.pullJoint.WorldAnchorB = targetLimb.SimPosition;
pullLimb.pullJoint.MaxForce = 5000.0f;
targetMovement *= 0.7f; //Carrying people like that takes a lot of effort.
if (target.AnimController.Dir != Dir)
target.AnimController.Flip();
}
else
{
pullLimb.pullJoint.WorldAnchorB = pullLimb.SimPosition + diff;
pullLimb.pullJoint.MaxForce = 5000.0f;
}
targetLimb.pullJoint.Enabled = true;
targetLimb.pullJoint.WorldAnchorB = targetLimb.SimPosition - diff;
targetLimb.pullJoint.MaxForce = 10000.0f;
if (targetLimb.type == LimbType.Torso)
{
targetLimb.pullJoint.WorldAnchorB = torso.SimPosition + (Vector2.UnitX * Dir) * 0.6f;
targetLimb.pullJoint.MaxForce = 300.0f;
}
else
{
targetLimb.pullJoint.WorldAnchorB = targetLimb.SimPosition - diff;
targetLimb.pullJoint.MaxForce = 5000.0f;
}
target.AnimController.movement = -diff;
}
@@ -1011,8 +1144,6 @@ namespace Barotrauma
public override void HoldItem(float deltaTime, Item item, Vector2[] handlePos, Vector2 holdPos, Vector2 aimPos, bool aim, float holdAngle)
{
Holdable holdable = item.GetComponent<Holdable>();
if (character.IsUnconscious || character.Stun > 0.0f) aim = false;
//calculate the handle positions
@@ -1030,7 +1161,6 @@ namespace Barotrauma
bool usingController = character.SelectedConstruction != null && character.SelectedConstruction.GetComponent<Controller>() != null;
float itemAngle;
if (Anim != Animation.Climbing && !usingController && character.Stun <= 0.0f && aim && itemPos != Vector2.Zero)
{
@@ -1042,6 +1172,7 @@ namespace Barotrauma
itemAngle = (torso.body.Rotation + holdAngle * Dir);
Holdable holdable = item.GetComponent<Holdable>();
if (holdable.ControlPose)
{
head.body.SmoothRotate(itemAngle);
@@ -7,6 +7,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
using Barotrauma.Items.Components;
using FarseerPhysics.Dynamics;
namespace Barotrauma
{
@@ -138,6 +139,27 @@ namespace Barotrauma
return info != null && !string.IsNullOrWhiteSpace(info.Name) ? info.Name : SpeciesName;
}
}
//Only used by server logs to determine "true identity" of the player for cases when they're disguised
public string LogName
{
get
{
return info != null && !string.IsNullOrWhiteSpace(info.Name) ? info.Name + (info.DisplayName != info.Name ? " (as " + info.DisplayName + ")" : "") : SpeciesName;
}
}
private float hideFaceTimer;
public bool HideFace
{
get
{
return hideFaceTimer > 0.0f;
}
set
{
hideFaceTimer = MathHelper.Clamp(hideFaceTimer + (value ? 1.0f : -0.5f), 0.0f, 10.0f);
}
}
public string ConfigPath
{
@@ -591,7 +613,7 @@ namespace Barotrauma
{
AnimController = new HumanoidAnimController(this, doc.Root.Element("ragdoll"));
AnimController.TargetDir = Direction.Right;
inventory = new CharacterInventory(16, this);
inventory = new CharacterInventory(17, this);
}
else
{
@@ -961,6 +983,56 @@ namespace Barotrauma
}
}
}
public bool CanSeeCharacter(Character character)
{
Limb selfLimb = AnimController.GetLimb(LimbType.Head);
if (selfLimb == null) selfLimb = AnimController.GetLimb(LimbType.Torso);
if (selfLimb == null) selfLimb = AnimController.Limbs[0];
Limb targetLimb = character.AnimController.GetLimb(LimbType.Head);
if (targetLimb == null) targetLimb = character.AnimController.GetLimb(LimbType.Torso);
if (targetLimb == null) targetLimb = character.AnimController.Limbs[0];
if (selfLimb != null && targetLimb != null)
{
Vector2 diff = ConvertUnits.ToSimUnits(targetLimb.WorldPosition - selfLimb.WorldPosition);
Body closestBody = null;
//both inside the same sub (or both outside)
//OR the we're inside, the other character outside
if (character.Submarine == Submarine || character.Submarine == null)
{
closestBody = Submarine.CheckVisibility(selfLimb.SimPosition, selfLimb.SimPosition + diff);
if (closestBody == null) return true;
}
//we're outside, the other character inside
else if (Submarine == null)
{
closestBody = Submarine.CheckVisibility(targetLimb.SimPosition, targetLimb.SimPosition - diff);
if (closestBody == null) return true;
}
//both inside different subs
else
{
closestBody = Submarine.CheckVisibility(selfLimb.SimPosition, selfLimb.SimPosition + diff);
if (closestBody != null && closestBody.UserData is Structure)
{
if (((Structure)closestBody.UserData).CastShadow) return false;
}
closestBody = Submarine.CheckVisibility(targetLimb.SimPosition, targetLimb.SimPosition - diff);
if (closestBody == null) return true;
}
Structure wall = closestBody.UserData as Structure;
return wall == null || !wall.CastShadow;
}
else
{
return false;
}
}
public bool HasEquippedItem(Item item)
{
@@ -1311,7 +1383,7 @@ namespace Barotrauma
findFocusedTimer -= deltaTime;
}
if (SelectedCharacter != null && IsKeyHit(InputType.Select))
if (SelectedCharacter != null && focusedItem == null && IsKeyHit(InputType.Select)) //Let people use ladders and buttons and stuff when dragging chars
{
DeselectCharacter();
}
@@ -1379,6 +1451,8 @@ namespace Barotrauma
public virtual void Update(float deltaTime, Camera cam)
{
UpdateProjSpecific(deltaTime, cam);
if (GameMain.Client != null && this == Controlled && !isSynced) return;
if (!Enabled) return;
@@ -1409,6 +1483,8 @@ namespace Barotrauma
item.Submarine = Submarine;
}
}
HideFace = false;
if (isDead) return;
@@ -1465,26 +1541,42 @@ namespace Barotrauma
}
}
//Skip health effects as critical health handles it differently
if (IsUnconscious)
{
UpdateUnconscious(deltaTime);
return;
}
//Do ragdoll shenanigans before Stun because it's still technically a stun, innit? Less network updates for us!
if (IsForceRagdolled)
IsRagdolled = IsForceRagdolled;
else if (!IsRagdolled || AnimController.Collider.LinearVelocity.Length() < 1f) //Keep us ragdolled if we were forced or we're too speedy to unragdoll
else if ((GameMain.Server == null || GameMain.Server.AllowRagdollButton) && (!IsRagdolled || AnimController.Collider.LinearVelocity.Length() < 1f)) //Keep us ragdolled if we were forced or we're too speedy to unragdoll
IsRagdolled = IsKeyDown(InputType.Ragdoll); //Handle this here instead of Control because we can stop being ragdolled ourselves
//Health effects
if (needsAir) UpdateOxygen(deltaTime);
Health -= bleeding * deltaTime;
Bleeding -= BleedingDecreaseSpeed * deltaTime;
if (health <= minHealth) Kill(CauseOfDeath.Bloodloss);
if (!IsDead) LockHands = false;
//ragdoll button
if (IsRagdolled)
{
if (AnimController is HumanoidAnimController) ((HumanoidAnimController)AnimController).Crouching = false;
if(GameMain.Server != null)
GameMain.Server.CreateEntityEvent(this, new object[] { NetEntityEvent.Type.Status });
AnimController.ResetPullJoints();
selectedConstruction = null;
return;
}
//AI and control stuff
Control(deltaTime, cam);
if (controlled != this && (!(this is AICharacter) || IsRemotePlayer))
{
@@ -1497,28 +1589,18 @@ namespace Barotrauma
selectedConstruction = null;
}
if (SelectedCharacter != null && AnimController.Anim == AnimController.Animation.CPR)
{
if (GameMain.Client == null) SelectedCharacter.Oxygen += (GetSkillLevel("Medical") / 10.0f) * deltaTime;
}
UpdateSightRange();
if (aiTarget != null) aiTarget.SoundRange = 0.0f;
lowPassMultiplier = MathHelper.Lerp(lowPassMultiplier, 1.0f, 0.1f);
if (needsAir) UpdateOxygen(deltaTime);
Health -= bleeding * deltaTime;
Bleeding -= BleedingDecreaseSpeed * deltaTime;
if (health <= minHealth) Kill(CauseOfDeath.Bloodloss);
if (!IsDead) LockHands = false;
//CPR stuff is handled in the UpdateCPR function in HumanoidAnimController
}
partial void UpdateControlled(float deltaTime, Camera cam);
partial void UpdateProjSpecific(float deltaTime, Camera cam);
private void UpdateOxygen(float deltaTime)
{
float prevOxygen = oxygen;
@@ -1552,12 +1634,17 @@ namespace Barotrauma
AnimController.ResetPullJoints();
selectedConstruction = null;
if (oxygen <= 0.0f) Oxygen -= deltaTime * 0.5f;
Oxygen -= deltaTime * 0.5f; //We're critical - our heart stopped!
if (health <= 0.0f)
if (health <= 0.0f) //Critical health - use current state for crit time
{
AddDamage(bleeding > 0.5f ? CauseOfDeath.Bloodloss : CauseOfDeath.Damage, Math.Max(bleeding, 1.0f) * deltaTime, null);
}
else //Keep on bleedin'
{
Health -= bleeding * deltaTime;
Bleeding -= BleedingDecreaseSpeed * deltaTime;
}
}
private void UpdateSightRange()
@@ -1634,7 +1721,7 @@ namespace Barotrauma
var attackingCharacter = attacker as Character;
if (attackingCharacter != null && attackingCharacter.AIController == null)
{
GameServer.Log(Name + " attacked by " + attackingCharacter.Name+". Damage: "+attackResult.Damage+" Bleeding damage: "+attackResult.Bleeding, ServerLog.MessageType.Attack);
GameServer.Log(LogName + " attacked by " + attackingCharacter.LogName +". Damage: "+attackResult.Damage+" Bleeding damage: "+attackResult.Bleeding, ServerLog.MessageType.Attack);
}
if (GameMain.Client == null &&
@@ -1799,7 +1886,7 @@ namespace Barotrauma
AnimController.Frozen = false;
GameServer.Log(Name+" has died (Cause of death: "+causeOfDeath+")", ServerLog.MessageType.Attack);
GameServer.Log(LogName+" has died (Cause of death: "+causeOfDeath+")", ServerLog.MessageType.Attack);
if (OnDeath != null) OnDeath(this, causeOfDeath);
@@ -12,7 +12,38 @@ namespace Barotrauma
partial class CharacterInfo
{
public string Name;
public string DisplayName
{
get
{
string disguiseName = "?";
if (Character == null || !Character.HideFace)
{
return Name;
}
if (Character.Inventory != null)
{
int cardSlotIndex = Character.Inventory.FindLimbSlot(InvSlotType.Card);
if (cardSlotIndex < 0) return disguiseName;
var idCard = Character.Inventory.Items[cardSlotIndex];
if (idCard == null) return disguiseName;
//Disguise as the ID card name if it's equipped
string[] readTags = idCard.Tags.Split(',');
foreach (string tag in readTags)
{
string[] s = tag.Split(':');
if (s[0] == "name")
{
return s[1];
}
}
}
return disguiseName;
}
}
public Character Character;
public readonly string File;
@@ -325,7 +325,7 @@ namespace Barotrauma
break;
case ClientNetObject.ENTITY_STATE:
int eventType = msg.ReadRangedInteger(0,2);
int eventType = msg.ReadRangedInteger(0,3);
switch (eventType)
{
case 0:
@@ -357,6 +357,9 @@ namespace Barotrauma
Kill(lastAttackCauseOfDeath);
}
break;
case 3:
AnimController.GrabLimb = (LimbType)msg.ReadUInt16();
break;
}
break;
}
@@ -436,6 +439,7 @@ namespace Barotrauma
if (AnimController is HumanoidAnimController)
{
tempBuffer.Write(((HumanoidAnimController)AnimController).Crouching);
tempBuffer.Write((UInt16)AnimController.GrabLimb);
}
bool hasAttackLimb = AnimController.Limbs.Any(l => l != null && l.attack != null);
@@ -534,6 +538,8 @@ namespace Barotrauma
msg.WriteRangedSingle(MathHelper.Clamp(Stun, 0.0f, MaxStun), 0.0f, MaxStun, 8);
}
msg.Write(IsRagdolled);
msg.Write(HuskInfectionState > 0.0f);
}
}
@@ -130,6 +130,10 @@ namespace Barotrauma
{
item.AddTag(s);
}
item.AddTag("name:" + character.Name);
item.AddTag("job:" + Name);
if (!string.IsNullOrWhiteSpace(spawnPoint.IdCardDesc))
item.Description = spawnPoint.IdCardDesc;
}
if (parentItem != null) parentItem.Combine(item);