From 48fb3d58b9631425c044400cfab1e4ea9139aaba Mon Sep 17 00:00:00 2001 From: Alex Noir Date: Fri, 8 Dec 2017 13:47:27 +0300 Subject: [PATCH 01/15] Let players choose to grab onto the body's torso! Better CPR animations todo: network the limb targeting --- .../Source/Characters/CharacterHUD.cs | 28 +++++ .../Characters/Animation/AnimController.cs | 2 + .../Animation/HumanoidAnimController.cs | 104 +++++++++++++----- 3 files changed, 104 insertions(+), 30 deletions(-) diff --git a/Barotrauma/BarotraumaClient/Source/Characters/CharacterHUD.cs b/Barotrauma/BarotraumaClient/Source/Characters/CharacterHUD.cs index f5d37e0b2..c7d01809a 100644 --- a/Barotrauma/BarotraumaClient/Source/Characters/CharacterHUD.cs +++ b/Barotrauma/BarotraumaClient/Source/Characters/CharacterHUD.cs @@ -13,6 +13,8 @@ namespace Barotrauma private static Sprite noiseOverlay, damageOverlay; private static GUIButton cprButton; + + private static GUIButton grabHoldButton; private static GUIButton suicideButton; @@ -41,6 +43,8 @@ namespace Barotrauma if (cprButton != null && cprButton.Visible) cprButton.AddToGUIUpdateList(); + if (grabHoldButton != null && cprButton.Visible) grabHoldButton.AddToGUIUpdateList(); + if (suicideButton != null && suicideButton.Visible) suicideButton.AddToGUIUpdateList(); if (!character.IsUnconscious && character.Stun <= 0.0f) @@ -89,6 +93,8 @@ namespace Barotrauma if (cprButton != null && cprButton.Visible) cprButton.Update(deltaTime); + if (grabHoldButton != null && grabHoldButton.Visible) grabHoldButton.Update(deltaTime); + if (suicideButton != null && suicideButton.Visible) suicideButton.Update(deltaTime); if (damageOverlayTimer > 0.0f) damageOverlayTimer -= deltaTime; @@ -195,9 +201,31 @@ namespace Barotrauma }; } + if (grabHoldButton == null) + { + grabHoldButton = new GUIButton( + new Rectangle(character.SelectedCharacter.Inventory.SlotPositions[0].ToPoint() + new Point(320, -60), new Point(130, 20)), + "Grabbing: " + (character.AnimController.GrabLimb == LimbType.Torso ? "Torso" : "Hands"), ""); + + grabHoldButton.OnClicked = (button, userData) => + { + if (Character.Controlled == null || Character.Controlled.SelectedCharacter == null) return false; + + character.AnimController.GrabLimb = character.AnimController.GrabLimb == LimbType.None ? LimbType.Torso : LimbType.None; + + if (GameMain.Client != null) + { + GameMain.Client.CreateEntityEvent(Character.Controlled, new object[] { NetEntityEvent.Type.Repair }); + } + grabHoldButton.Text = "Grabbing: " + (character.AnimController.GrabLimb == LimbType.Torso ? "Torso" : "Hands"); + return true; + }; + } + //cprButton.Visible = character.GetSkillLevel("Medical") > 20.0f; if (cprButton.Visible) cprButton.Draw(spriteBatch); + if (grabHoldButton.Visible) grabHoldButton.Draw(spriteBatch); } if (character.FocusedCharacter != null && character.FocusedCharacter.CanBeSelected) diff --git a/Barotrauma/BarotraumaShared/Source/Characters/Animation/AnimController.cs b/Barotrauma/BarotraumaShared/Source/Characters/Animation/AnimController.cs index 28cfc35c4..7fcc25d17 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/Animation/AnimController.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/Animation/AnimController.cs @@ -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; diff --git a/Barotrauma/BarotraumaShared/Source/Characters/Animation/HumanoidAnimController.cs b/Barotrauma/BarotraumaShared/Source/Characters/Animation/HumanoidAnimController.cs index 9c9a70b4a..19178201f 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/Animation/HumanoidAnimController.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/Animation/HumanoidAnimController.cs @@ -20,6 +20,7 @@ namespace Barotrauma private float thighTorque; private float cprAnimState; + private float cprPump; private float inWaterTimer; private bool swimming; @@ -882,8 +883,11 @@ namespace Barotrauma Crouching = true; Vector2 diff = character.SelectedCharacter.SimPosition - character.SimPosition; - var targetHead = character.SelectedCharacter.AnimController.GetLimb(LimbType.Head); - + Limb targetHead = character.SelectedCharacter.AnimController.GetLimb(LimbType.Head); + Limb targetTorso = character.SelectedCharacter.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); @@ -891,21 +895,41 @@ 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(); + 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; + } + 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; + } + cprPump += deltaTime; + } - var head = GetLimb(LimbType.Head); - head.pullJoint.WorldAnchorB = new Vector2(targetHead.SimPosition.X, targetHead.SimPosition.Y + 0.6f + yPos); - head.pullJoint.Enabled = true; + 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); @@ -918,31 +942,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) @@ -954,12 +981,29 @@ 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. + } + 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; } From fff8d714fe421fcd08425065a71c1247db94916d Mon Sep 17 00:00:00 2001 From: Alex Noir Date: Fri, 8 Dec 2017 14:09:09 +0300 Subject: [PATCH 02/15] I THINK this is all that needs to be done to network it...right? --- .../BarotraumaClient/Source/Characters/CharacterNetworking.cs | 1 + .../BarotraumaShared/Source/Characters/CharacterNetworking.cs | 1 + 2 files changed, 2 insertions(+) diff --git a/Barotrauma/BarotraumaClient/Source/Characters/CharacterNetworking.cs b/Barotrauma/BarotraumaClient/Source/Characters/CharacterNetworking.cs index ec44d08af..12367f179 100644 --- a/Barotrauma/BarotraumaClient/Source/Characters/CharacterNetworking.cs +++ b/Barotrauma/BarotraumaClient/Source/Characters/CharacterNetworking.cs @@ -91,6 +91,7 @@ namespace Barotrauma bool crouching = msg.ReadBoolean(); keys[(int)InputType.Crouch].Held = crouching; keys[(int)InputType.Crouch].SetState(false, crouching); + AnimController.GrabLimb = (LimbType)msg.ReadInt16(); } bool hasAttackLimb = msg.ReadBoolean(); diff --git a/Barotrauma/BarotraumaShared/Source/Characters/CharacterNetworking.cs b/Barotrauma/BarotraumaShared/Source/Characters/CharacterNetworking.cs index 5abc8331e..a0eabba53 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/CharacterNetworking.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/CharacterNetworking.cs @@ -429,6 +429,7 @@ namespace Barotrauma if (AnimController is HumanoidAnimController) { tempBuffer.Write(((HumanoidAnimController)AnimController).Crouching); + tempBuffer.Write((int)((HumanoidAnimController)AnimController).GrabLimb); } bool hasAttackLimb = AnimController.Limbs.Any(l => l != null && l.attack != null); From 286f290e573df49e091760e691306ec10591afe6 Mon Sep 17 00:00:00 2001 From: Alex Noir Date: Fri, 8 Dec 2017 15:32:37 +0300 Subject: [PATCH 03/15] Fixed networking --- .../Source/Characters/CharacterHUD.cs | 8 +++++++- .../Source/Characters/CharacterNetworking.cs | 12 ++++++++---- .../Source/Characters/CharacterNetworking.cs | 7 +++++-- 3 files changed, 20 insertions(+), 7 deletions(-) diff --git a/Barotrauma/BarotraumaClient/Source/Characters/CharacterHUD.cs b/Barotrauma/BarotraumaClient/Source/Characters/CharacterHUD.cs index c58217cfd..46586ed9d 100644 --- a/Barotrauma/BarotraumaClient/Source/Characters/CharacterHUD.cs +++ b/Barotrauma/BarotraumaClient/Source/Characters/CharacterHUD.cs @@ -213,10 +213,16 @@ namespace Barotrauma character.AnimController.GrabLimb = character.AnimController.GrabLimb == LimbType.None ? LimbType.Torso : LimbType.None; + foreach (Limb limb in Character.Controlled.SelectedCharacter.AnimController.Limbs) + { + limb.pullJoint.Enabled = false; + } + if (GameMain.Client != null) { - GameMain.Client.CreateEntityEvent(Character.Controlled, new object[] { NetEntityEvent.Type.Repair }); + GameMain.Client.CreateEntityEvent(Character.Controlled, new object[] { NetEntityEvent.Type.Control }); } + grabHoldButton.Text = "Grabbing: " + (character.AnimController.GrabLimb == LimbType.Torso ? "Torso" : "Hands"); return true; }; diff --git a/Barotrauma/BarotraumaClient/Source/Characters/CharacterNetworking.cs b/Barotrauma/BarotraumaClient/Source/Characters/CharacterNetworking.cs index 12367f179..f9983ec4e 100644 --- a/Barotrauma/BarotraumaClient/Source/Characters/CharacterNetworking.cs +++ b/Barotrauma/BarotraumaClient/Source/Characters/CharacterNetworking.cs @@ -17,15 +17,19 @@ namespace Barotrauma switch ((NetEntityEvent.Type)extraData[0]) { case NetEntityEvent.Type.InventoryState: - msg.WriteRangedInteger(0, 2, 0); + msg.WriteRangedInteger(0, 3, 0); inventory.ClientWrite(msg, extraData); break; case NetEntityEvent.Type.Repair: - msg.WriteRangedInteger(0, 2, 1); + msg.WriteRangedInteger(0, 3, 1); msg.Write(AnimController.Anim == AnimController.Animation.CPR); break; case NetEntityEvent.Type.Status: - msg.WriteRangedInteger(0, 2, 2); + msg.WriteRangedInteger(0, 3, 2); + break; + case NetEntityEvent.Type.Control: + msg.WriteRangedInteger(0, 3, 3); + msg.Write((int)AnimController.GrabLimb); break; } } @@ -91,7 +95,7 @@ namespace Barotrauma bool crouching = msg.ReadBoolean(); keys[(int)InputType.Crouch].Held = crouching; keys[(int)InputType.Crouch].SetState(false, crouching); - AnimController.GrabLimb = (LimbType)msg.ReadInt16(); + AnimController.GrabLimb = (LimbType)msg.ReadInt32(); } bool hasAttackLimb = msg.ReadBoolean(); diff --git a/Barotrauma/BarotraumaShared/Source/Characters/CharacterNetworking.cs b/Barotrauma/BarotraumaShared/Source/Characters/CharacterNetworking.cs index 197eac64d..cf1598c3c 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/CharacterNetworking.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/CharacterNetworking.cs @@ -324,7 +324,7 @@ namespace Barotrauma break; case ClientNetObject.ENTITY_STATE: - int eventType = msg.ReadRangedInteger(0,2); + int eventType = msg.ReadRangedInteger(0,3); switch (eventType) { case 0: @@ -356,6 +356,9 @@ namespace Barotrauma Kill(lastAttackCauseOfDeath); } break; + case 3: + AnimController.GrabLimb = (LimbType)msg.ReadInt32(); + break; } break; } @@ -435,7 +438,7 @@ namespace Barotrauma if (AnimController is HumanoidAnimController) { tempBuffer.Write(((HumanoidAnimController)AnimController).Crouching); - tempBuffer.Write((int)((HumanoidAnimController)AnimController).GrabLimb); + tempBuffer.Write((int)AnimController.GrabLimb); } bool hasAttackLimb = AnimController.Limbs.Any(l => l != null && l.attack != null); From de7489db8b687eccd2c76321da6a3c5df81f4c36 Mon Sep 17 00:00:00 2001 From: Alex Noir Date: Fri, 8 Dec 2017 20:55:46 +0300 Subject: [PATCH 04/15] Change int to UInt32 for grabLimb networking Fixed IsRagdolled state networking --- .../Source/Characters/CharacterNetworking.cs | 7 +++++-- Barotrauma/BarotraumaShared/Source/Characters/Character.cs | 6 ++++-- .../Source/Characters/CharacterNetworking.cs | 6 ++++-- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/Barotrauma/BarotraumaClient/Source/Characters/CharacterNetworking.cs b/Barotrauma/BarotraumaClient/Source/Characters/CharacterNetworking.cs index f9983ec4e..2b9015be1 100644 --- a/Barotrauma/BarotraumaClient/Source/Characters/CharacterNetworking.cs +++ b/Barotrauma/BarotraumaClient/Source/Characters/CharacterNetworking.cs @@ -29,7 +29,7 @@ namespace Barotrauma break; case NetEntityEvent.Type.Control: msg.WriteRangedInteger(0, 3, 3); - msg.Write((int)AnimController.GrabLimb); + msg.Write((UInt16)AnimController.GrabLimb); break; } } @@ -95,7 +95,7 @@ namespace Barotrauma bool crouching = msg.ReadBoolean(); keys[(int)InputType.Crouch].Held = crouching; keys[(int)InputType.Crouch].SetState(false, crouching); - AnimController.GrabLimb = (LimbType)msg.ReadInt32(); + AnimController.GrabLimb = (LimbType)msg.ReadUInt16(); } bool hasAttackLimb = msg.ReadBoolean(); @@ -371,6 +371,9 @@ namespace Barotrauma SetStun(0.0f, true, true); } + bool ragdolled = msg.ReadBoolean(); + IsRagdolled = ragdolled; + bool huskInfected = msg.ReadBoolean(); if (huskInfected) { diff --git a/Barotrauma/BarotraumaShared/Source/Characters/Character.cs b/Barotrauma/BarotraumaShared/Source/Characters/Character.cs index a506e62d1..5b3dacbdf 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/Character.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/Character.cs @@ -1468,15 +1468,17 @@ namespace Barotrauma 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 (!IsRagdolled || (GameMain.Server != null && 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 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; diff --git a/Barotrauma/BarotraumaShared/Source/Characters/CharacterNetworking.cs b/Barotrauma/BarotraumaShared/Source/Characters/CharacterNetworking.cs index cf1598c3c..28ab23947 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/CharacterNetworking.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/CharacterNetworking.cs @@ -357,7 +357,7 @@ namespace Barotrauma } break; case 3: - AnimController.GrabLimb = (LimbType)msg.ReadInt32(); + AnimController.GrabLimb = (LimbType)msg.ReadUInt16(); break; } break; @@ -438,7 +438,7 @@ namespace Barotrauma if (AnimController is HumanoidAnimController) { tempBuffer.Write(((HumanoidAnimController)AnimController).Crouching); - tempBuffer.Write((int)AnimController.GrabLimb); + tempBuffer.Write((UInt16)AnimController.GrabLimb); } bool hasAttackLimb = AnimController.Limbs.Any(l => l != null && l.attack != null); @@ -536,6 +536,8 @@ namespace Barotrauma msg.WriteRangedSingle(MathHelper.Clamp(Stun, 0.0f, MaxStun), 0.0f, MaxStun, 8); } + msg.Write(IsRagdolled); + msg.Write(HuskInfectionState > 0.0f); } } From e0504042784c27df6b16695cf9f476f9866a8c23 Mon Sep 17 00:00:00 2001 From: Alex Noir Date: Fri, 8 Dec 2017 22:30:47 +0300 Subject: [PATCH 05/15] Carrying stunned/unconscious/dead people up ladders woot!!! Properly orient grabbed player on climbing and shoulder grab Allow interaction with buttons, ladders, etc. when grabbing someone --- .../Animation/HumanoidAnimController.cs | 38 +++++++++++++++++-- .../Source/Characters/Character.cs | 2 +- 2 files changed, 36 insertions(+), 4 deletions(-) diff --git a/Barotrauma/BarotraumaShared/Source/Characters/Animation/HumanoidAnimController.cs b/Barotrauma/BarotraumaShared/Source/Characters/Animation/HumanoidAnimController.cs index 19178201f..cd7567166 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/Animation/HumanoidAnimController.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/Animation/HumanoidAnimController.cs @@ -869,7 +869,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) @@ -880,11 +907,13 @@ namespace Barotrauma return; } + Character target = character.SelectedCharacter; + Crouching = true; - Vector2 diff = character.SelectedCharacter.SimPosition - character.SimPosition; - Limb targetHead = character.SelectedCharacter.AnimController.GetLimb(LimbType.Head); - Limb targetTorso = character.SelectedCharacter.AnimController.GetLimb(LimbType.Torso); + 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); @@ -986,6 +1015,9 @@ namespace Barotrauma 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 { diff --git a/Barotrauma/BarotraumaShared/Source/Characters/Character.cs b/Barotrauma/BarotraumaShared/Source/Characters/Character.cs index 5b3dacbdf..88d5d70fe 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/Character.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/Character.cs @@ -1308,7 +1308,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(); } From 07aeac4fdc94804e147f7c8502bb7768a288934a Mon Sep 17 00:00:00 2001 From: Alex Noir Date: Sat, 9 Dec 2017 19:09:10 +0300 Subject: [PATCH 06/15] Traitor Count/Coefficient and Ragdoll and Karma server settings buttons!!! oh my GOD!!! --- .../Source/Networking/GameServerSettings.cs | 83 ++++++++++++++++++- .../Source/Characters/Character.cs | 2 +- .../Source/Networking/GameServerSettings.cs | 21 +++++ 3 files changed, 102 insertions(+), 4 deletions(-) diff --git a/Barotrauma/BarotraumaClient/Source/Networking/GameServerSettings.cs b/Barotrauma/BarotraumaClient/Source/Networking/GameServerSettings.cs index 7c694d39a..229fe6432 100644 --- a/Barotrauma/BarotraumaClient/Source/Networking/GameServerSettings.cs +++ b/Barotrauma/BarotraumaClient/Source/Networking/GameServerSettings.cs @@ -320,7 +320,7 @@ namespace Barotrauma.Networking return true; }; - y += 40; + y += 20; var voteKickBox = new GUITickBox(new Rectangle(0, y, 20, 20), "Allow vote kicking", Alignment.Left, settingsTabs[1]); voteKickBox.Selected = Voting.AllowVoteKick; @@ -357,7 +357,7 @@ namespace Barotrauma.Networking return true; }; - y += 40; + y += 20; var randomizeLevelBox = new GUITickBox(new Rectangle(0, y, 20, 20), "Randomize level seed between rounds", Alignment.Left, settingsTabs[1]); randomizeLevelBox.Selected = RandomizeSeed; @@ -367,7 +367,7 @@ namespace Barotrauma.Networking return true; }; - y += 40; + y += 20; var saveLogsBox = new GUITickBox(new Rectangle(0, y, 20, 20), "Save server logs", Alignment.Left, settingsTabs[1]); saveLogsBox.Selected = SaveServerLogs; @@ -378,6 +378,83 @@ namespace Barotrauma.Networking return true; }; + y += 20; + + var ragdollButtonBox = new GUITickBox(new Rectangle(0, y, 20, 20), "Allow ragdoll button", Alignment.Left, settingsTabs[1]); + ragdollButtonBox.Selected = AllowRagdollButton; + ragdollButtonBox.OnSelected = (GUITickBox) => + { + AllowRagdollButton = GUITickBox.Selected; + return true; + }; + + y += 20; + + var traitorRatioBox = new GUITickBox(new Rectangle(0, y, 20, 20), "Use % of players for max traitors", Alignment.Left, settingsTabs[1]); + var traitorRatioText = new GUITextBlock(new Rectangle(20, y + 20, 20, 20), "Traitor ratio: 20 %", "", settingsTabs[1], GUI.SmallFont); + var traitorRatioSlider = new GUIScrollBar(new Rectangle(150, y + 22, 100, 15), "", 0.1f, settingsTabs[1]); + //Prepare the slider before the tick box + if (traitorUseRatio) + { + traitorRatioSlider.UserData = traitorRatioText; + traitorRatioSlider.Step = 0.01f; //Lots of fine-tuning + traitorRatioSlider.BarScroll = (traitorRatio - 0.1f) / 0.9f; + } + else + { + traitorRatioSlider.UserData = traitorRatioText; + traitorRatioSlider.Step = 1f / (maxPlayers-1); + traitorRatioSlider.BarScroll = MathUtils.Round(traitorRatio, 1f); + } + //Slider END + + traitorRatioBox.Selected = traitorUseRatio; + traitorRatioBox.OnSelected = (GUITickBox) => + { + traitorUseRatio = GUITickBox.Selected; + //Affect the slider graphics + if (traitorUseRatio) + { + traitorRatioSlider.UserData = traitorRatioText; + traitorRatioSlider.Step = 0.01f; //Lots of fine-tuning + traitorRatioSlider.BarScroll = 0.2f; //default values + traitorRatioSlider.OnMoved(traitorRatioSlider, traitorRatioSlider.BarScroll); //Update the scroll bar + } + else + { + traitorRatioSlider.UserData = traitorRatioText; + traitorRatioSlider.Step = 1f / (maxPlayers-1); + traitorRatioSlider.BarScroll = 1; //default values + traitorRatioSlider.OnMoved(traitorRatioSlider, traitorRatioSlider.BarScroll); //Update the scroll bar + } + return true; + }; + traitorRatioSlider.OnMoved = (GUIScrollBar scrollBar, float barScroll) => + { + GUITextBlock traitorText = scrollBar.UserData as GUITextBlock; + if (traitorUseRatio) + { + traitorRatio = barScroll * 0.9f + 0.1f; + traitorText.Text = "Traitor ratio: " + (int)MathUtils.Round(traitorRatio * 100.0f, 1.0f) + " %"; + } + else + { + traitorRatio = MathUtils.Round(barScroll * (maxPlayers-1), 1f) + 1; + traitorText.Text = "Traitor count: " + traitorRatio; + } + return true; + }; + traitorRatioSlider.OnMoved(traitorRatioSlider, traitorRatioSlider.BarScroll); + + y += 45; + + var karmaButtonBox = new GUITickBox(new Rectangle(0, y, 20, 20), "Use Karma", Alignment.Left, settingsTabs[1]); + karmaButtonBox.Selected = KarmaEnabled; + karmaButtonBox.OnSelected = (GUITickBox) => + { + KarmaEnabled = GUITickBox.Selected; + return true; + }; //-------------------------------------------------------------------------------- // banlist diff --git a/Barotrauma/BarotraumaShared/Source/Characters/Character.cs b/Barotrauma/BarotraumaShared/Source/Characters/Character.cs index 88d5d70fe..198eb25d4 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/Character.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/Character.cs @@ -1471,7 +1471,7 @@ namespace Barotrauma //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 || (GameMain.Server != null && 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 if (IsRagdolled) diff --git a/Barotrauma/BarotraumaShared/Source/Networking/GameServerSettings.cs b/Barotrauma/BarotraumaShared/Source/Networking/GameServerSettings.cs index ade900b05..b597f341c 100644 --- a/Barotrauma/BarotraumaShared/Source/Networking/GameServerSettings.cs +++ b/Barotrauma/BarotraumaShared/Source/Networking/GameServerSettings.cs @@ -130,6 +130,13 @@ namespace Barotrauma.Networking private set; } + [Serialize(true, true)] + public bool AllowRagdollButton + { + get; + private set; + } + [Serialize(true, true)] public bool AllowFileTransfers { @@ -210,6 +217,20 @@ namespace Barotrauma.Networking private set; } + [Serialize(true, true)] + public bool traitorUseRatio + { + get; + private set; + } + + [Serialize(0.2f, true)] + public float traitorRatio + { + get; + private set; + } + [Serialize(false,true)] public bool KarmaEnabled { From ffba72c750b0acbcc289aa16e6cc36641fc33f75 Mon Sep 17 00:00:00 2001 From: Alex Noir Date: Sat, 9 Dec 2017 19:13:21 +0300 Subject: [PATCH 07/15] Forgot to put new settings into the .xml --- Barotrauma/BarotraumaShared/serversettings.xml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Barotrauma/BarotraumaShared/serversettings.xml b/Barotrauma/BarotraumaShared/serversettings.xml index 1eb8f2d21..c2da717b4 100644 --- a/Barotrauma/BarotraumaShared/serversettings.xml +++ b/Barotrauma/BarotraumaShared/serversettings.xml @@ -15,11 +15,15 @@ allowspectating="True" endroundatlevelend="True" saveserverlogs="True" + allowragdollbutton="True" allowfiletransfers="True" allowrespawn="True" allowvotekick="True" endvoterequiredratio="0.6" kickvoterequiredratio="0.6" + traitoruseratio="True" + traitorratio="0.2" + karmaenabled="True" SubSelection="Manual" ModeSelection="Manual" TraitorsEnabled="No" From 04707232ded447a94f6c92ee8543ef6483ea9f2b Mon Sep 17 00:00:00 2001 From: Alex Noir Date: Sat, 9 Dec 2017 19:15:51 +0300 Subject: [PATCH 08/15] forgot to remove the console command for karma --- Barotrauma/BarotraumaShared/Source/DebugConsole.cs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/Barotrauma/BarotraumaShared/Source/DebugConsole.cs b/Barotrauma/BarotraumaShared/Source/DebugConsole.cs index 15b2e7ffa..237718d75 100644 --- a/Barotrauma/BarotraumaShared/Source/DebugConsole.cs +++ b/Barotrauma/BarotraumaShared/Source/DebugConsole.cs @@ -419,12 +419,6 @@ namespace Barotrauma }); })); - commands.Add(new Command("togglekarma", "togglekarma: Toggles the karma system.", (string[] args) => - { - if (GameMain.Server == null) return; - GameMain.Server.KarmaEnabled = !GameMain.Server.KarmaEnabled; - })); - commands.Add(new Command("kick", "kick [name]: Kick a player out of the server.", (string[] args) => { if (GameMain.NetworkMember == null || args.Length == 0) return; From 383d9f3aab0442bd3d068b37272e086d6ab878de Mon Sep 17 00:00:00 2001 From: Alex Noir Date: Wed, 13 Dec 2017 21:29:54 +0300 Subject: [PATCH 09/15] Karma too unfinished to be enabled by default --- Barotrauma/BarotraumaShared/serversettings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Barotrauma/BarotraumaShared/serversettings.xml b/Barotrauma/BarotraumaShared/serversettings.xml index c2da717b4..18abd505a 100644 --- a/Barotrauma/BarotraumaShared/serversettings.xml +++ b/Barotrauma/BarotraumaShared/serversettings.xml @@ -23,7 +23,7 @@ kickvoterequiredratio="0.6" traitoruseratio="True" traitorratio="0.2" - karmaenabled="True" + karmaenabled="False" SubSelection="Manual" ModeSelection="Manual" TraitorsEnabled="No" From ff55140ce3b6b67e827a879023a2dbc011780fbe Mon Sep 17 00:00:00 2001 From: Alex Noir Date: Thu, 14 Dec 2017 19:07:53 +0300 Subject: [PATCH 10/15] Revert "forgot to remove the console command for karma" This reverts commit 04707232ded447a94f6c92ee8543ef6483ea9f2b. --- Barotrauma/BarotraumaShared/Source/DebugConsole.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Barotrauma/BarotraumaShared/Source/DebugConsole.cs b/Barotrauma/BarotraumaShared/Source/DebugConsole.cs index 237718d75..15b2e7ffa 100644 --- a/Barotrauma/BarotraumaShared/Source/DebugConsole.cs +++ b/Barotrauma/BarotraumaShared/Source/DebugConsole.cs @@ -419,6 +419,12 @@ namespace Barotrauma }); })); + commands.Add(new Command("togglekarma", "togglekarma: Toggles the karma system.", (string[] args) => + { + if (GameMain.Server == null) return; + GameMain.Server.KarmaEnabled = !GameMain.Server.KarmaEnabled; + })); + commands.Add(new Command("kick", "kick [name]: Kick a player out of the server.", (string[] args) => { if (GameMain.NetworkMember == null || args.Length == 0) return; From 141214eadc6f4aa1e8d46d2f770b66cdf585bb7b Mon Sep 17 00:00:00 2001 From: Alex Noir Date: Thu, 14 Dec 2017 19:08:17 +0300 Subject: [PATCH 11/15] Fix infinitely repairing karma by welding fixed hulls --- Barotrauma/BarotraumaShared/Source/Map/Structure.cs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/Barotrauma/BarotraumaShared/Source/Map/Structure.cs b/Barotrauma/BarotraumaShared/Source/Map/Structure.cs index a9f7f8330..06d60a7e0 100644 --- a/Barotrauma/BarotraumaShared/Source/Map/Structure.cs +++ b/Barotrauma/BarotraumaShared/Source/Map/Structure.cs @@ -678,14 +678,13 @@ namespace Barotrauma if (!MathUtils.IsValid(damage)) return; - float damageDiff = damage - sections[sectionIndex].damage; + if (GameMain.Server != null && damage != sections[sectionIndex].damage) { GameMain.Server.CreateEntityEvent(this); } - AdjustKarma(attacker, damageDiff); if (damage < prefab.Health*0.5f) { if (sections[sectionIndex].gap != null) @@ -717,10 +716,14 @@ namespace Barotrauma sections[sectionIndex].gap.Open = (damage / prefab.Health - 0.5f) * 2.0f; } - + + float damageDiff = damage - sections[sectionIndex].damage; bool hadHole = SectionBodyDisabled(sectionIndex); sections[sectionIndex].damage = MathHelper.Clamp(damage, 0.0f, prefab.Health); + if (sections[sectionIndex].damage < prefab.Health) //otherwise it's possible to infinitely gain karma by welding fixed things + AdjustKarma(attacker, damageDiff); + bool hasHole = SectionBodyDisabled(sectionIndex); if (hadHole == hasHole) return; From e5c49d929d306a9a390fa754a9c7881f1f64a985 Mon Sep 17 00:00:00 2001 From: Alex Noir Date: Sun, 17 Dec 2017 23:13:50 +0300 Subject: [PATCH 12/15] Fixed ragdolling and grab-type switching in singleplayer --- Barotrauma/BarotraumaClient/Source/Characters/CharacterHUD.cs | 4 ++-- Barotrauma/BarotraumaShared/Source/Characters/Character.cs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Barotrauma/BarotraumaClient/Source/Characters/CharacterHUD.cs b/Barotrauma/BarotraumaClient/Source/Characters/CharacterHUD.cs index bed626321..a2c3e861b 100644 --- a/Barotrauma/BarotraumaClient/Source/Characters/CharacterHUD.cs +++ b/Barotrauma/BarotraumaClient/Source/Characters/CharacterHUD.cs @@ -211,7 +211,7 @@ namespace Barotrauma { if (Character.Controlled == null || Character.Controlled.SelectedCharacter == null) return false; - character.AnimController.GrabLimb = character.AnimController.GrabLimb == LimbType.None ? LimbType.Torso : LimbType.None; + Character.Controlled.AnimController.GrabLimb = Character.Controlled.AnimController.GrabLimb == LimbType.None ? LimbType.Torso : LimbType.None; foreach (Limb limb in Character.Controlled.SelectedCharacter.AnimController.Limbs) { @@ -223,7 +223,7 @@ namespace Barotrauma GameMain.Client.CreateEntityEvent(Character.Controlled, new object[] { NetEntityEvent.Type.Control }); } - grabHoldButton.Text = "Grabbing: " + (character.AnimController.GrabLimb == LimbType.Torso ? "Torso" : "Hands"); + grabHoldButton.Text = "Grabbing: " + (Character.Controlled.AnimController.GrabLimb == LimbType.Torso ? "Torso" : "Hands"); return true; }; } diff --git a/Barotrauma/BarotraumaShared/Source/Characters/Character.cs b/Barotrauma/BarotraumaShared/Source/Characters/Character.cs index a6035ccf5..c6ae2591e 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/Character.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/Character.cs @@ -1499,7 +1499,7 @@ namespace Barotrauma //Do ragdoll shenanigans before Stun because it's still technically a stun, innit? Less network updates for us! if (IsForceRagdolled) IsRagdolled = IsForceRagdolled; - 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 + 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 if (IsRagdolled) From 3343185e9f68c245e199e8673cd24039c99d62de Mon Sep 17 00:00:00 2001 From: Alex Noir Date: Sun, 17 Dec 2017 23:25:17 +0300 Subject: [PATCH 13/15] Make radios drain battery when idle so they're no longer infinite when not equipped in face slot Reduce drainage rate due to original drain rate being too quick though However: radios will still drain battery even when dropped or put in a locker. This could be solved by either implementing a conditional into .xml which would check if a character exists, orrrr by adding a toggle in-inventory button, orrrr by allowing a third "toggle" param for booleans e.g. "OnUse" IsActive="toggle" --- .../BarotraumaShared/Content/Items/Jobgear/misc.xml | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/Barotrauma/BarotraumaShared/Content/Items/Jobgear/misc.xml b/Barotrauma/BarotraumaShared/Content/Items/Jobgear/misc.xml index cdb8cb115..c94e03422 100644 --- a/Barotrauma/BarotraumaShared/Content/Items/Jobgear/misc.xml +++ b/Barotrauma/BarotraumaShared/Content/Items/Jobgear/misc.xml @@ -14,13 +14,16 @@ - - - - + + + + + + + + - From 3b65802a9584a57d2eddc333497e6e73ecf440af Mon Sep 17 00:00:00 2001 From: Alex Noir Date: Tue, 19 Dec 2017 15:25:01 +0300 Subject: [PATCH 14/15] Fix issue #97 by allowing stunned people to sustain bleed + oxygen damage as well as handling crit health effects differently --- .../Source/Characters/Character.cs | 33 ++++++++++++------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/Barotrauma/BarotraumaShared/Source/Characters/Character.cs b/Barotrauma/BarotraumaShared/Source/Characters/Character.cs index c6ae2591e..737abc64d 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/Character.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/Character.cs @@ -1490,6 +1490,7 @@ namespace Barotrauma } } + //Skip health effects as critical health handles it differently if (IsUnconscious) { UpdateUnconscious(deltaTime); @@ -1502,6 +1503,17 @@ namespace Barotrauma 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; @@ -1512,6 +1524,8 @@ namespace Barotrauma return; } + //AI and control stuff + Control(deltaTime, cam); if (controlled != this && (!(this is AICharacter) || IsRemotePlayer)) { @@ -1533,15 +1547,6 @@ namespace Barotrauma 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; } partial void UpdateControlled(float deltaTime, Camera cam); @@ -1581,12 +1586,18 @@ namespace Barotrauma AnimController.ResetPullJoints(); selectedConstruction = null; - if (oxygen <= 0.0f) Oxygen -= deltaTime * 0.5f; + if (oxygen <= 0.0f) Oxygen -= deltaTime * 0.5f; //Slow down oxygen consumption to increase time in crit + else if (needsAir) UpdateOxygen(deltaTime); //So you can't simply cheat out of requiring oxygen when crit - 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() From e56f5c49467aeb06c15863fd70aa92078b748671 Mon Sep 17 00:00:00 2001 From: Alex Noir Date: Tue, 19 Dec 2017 22:11:45 +0300 Subject: [PATCH 15/15] what started as a fix of https://github.com/Regalis11/Barotrauma/issues/103 ended up being a huge CPR overhaul. oops. CPR: There's now a difference between CPR on bleeding, CPR on hurting and CPR on oxygen deprivation. If you try to CPR bleeding people, it will make bloody sounds and particles while hurting them. So don't. If you CPR people with less than 0 health, it will do RNG based on your skill level to bring them back to life with 2 HP. Otherwise if you CPR their oxygen back, chest pumps will simply prevent oxygen deprivation and mouth-to-mouth will bring back their oxygen while taking yours based on the skill level. Crit: Changed it so you always lose oxygen when critical. Your heart stopped either way! --- .../Animation/HumanoidAnimController.cs | 63 +++++++++++++++++++ .../Source/Characters/Character.cs | 10 +-- 2 files changed, 66 insertions(+), 7 deletions(-) diff --git a/Barotrauma/BarotraumaShared/Source/Characters/Animation/HumanoidAnimController.cs b/Barotrauma/BarotraumaShared/Source/Characters/Animation/HumanoidAnimController.cs index 18b1316a0..d77bc2bac 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/Animation/HumanoidAnimController.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/Animation/HumanoidAnimController.cs @@ -933,6 +933,17 @@ namespace Barotrauma Grab(handPos, handPos); Vector2 colliderPos = GetColliderBottom(); + + 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; @@ -940,6 +951,16 @@ namespace Barotrauma 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 { @@ -952,6 +973,48 @@ namespace Barotrauma 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); + float bloodParticleAmount = 4; + float bloodParticleSize = 1.0f; + + for (int i = 0; i < bloodParticleAmount; i++) + { + var blood = GameMain.ParticleManager.CreateParticle(inWater ? "waterblood" : "blood", targetTorso.WorldPosition, Rand.Vector(10.0f), 0.0f, target.AnimController.CurrentHull); + if (blood != null) + { + blood.Size *= bloodParticleSize; + } + } +#endif + } + } } cprPump += deltaTime; } diff --git a/Barotrauma/BarotraumaShared/Source/Characters/Character.cs b/Barotrauma/BarotraumaShared/Source/Characters/Character.cs index 737abc64d..a1de13a8f 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/Character.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/Character.cs @@ -1538,15 +1538,12 @@ 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); + + //CPR stuff is handled in the UpdateCPR function in HumanoidAnimController } partial void UpdateControlled(float deltaTime, Camera cam); @@ -1586,8 +1583,7 @@ namespace Barotrauma AnimController.ResetPullJoints(); selectedConstruction = null; - if (oxygen <= 0.0f) Oxygen -= deltaTime * 0.5f; //Slow down oxygen consumption to increase time in crit - else if (needsAir) UpdateOxygen(deltaTime); //So you can't simply cheat out of requiring oxygen when crit + Oxygen -= deltaTime * 0.5f; //We're critical - our heart stopped! if (health <= 0.0f) //Critical health - use current state for crit time {