diff --git a/Barotrauma/BarotraumaClient/Source/Characters/CharacterHUD.cs b/Barotrauma/BarotraumaClient/Source/Characters/CharacterHUD.cs
index 8a9f1ebc4..a2c3e861b 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,37 @@ 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.Controlled.AnimController.GrabLimb = Character.Controlled.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.Control });
+ }
+
+ grabHoldButton.Text = "Grabbing: " + (Character.Controlled.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/BarotraumaClient/Source/Characters/CharacterNetworking.cs b/Barotrauma/BarotraumaClient/Source/Characters/CharacterNetworking.cs
index 82418a2a4..51d728219 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((UInt16)AnimController.GrabLimb);
break;
}
}
@@ -91,6 +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.ReadUInt16();
}
bool hasAttackLimb = msg.ReadBoolean();
@@ -367,6 +372,9 @@ namespace Barotrauma
SetStun(0.0f, true, true);
}
+ bool ragdolled = msg.ReadBoolean();
+ IsRagdolled = ragdolled;
+
bool huskInfected = msg.ReadBoolean();
if (huskInfected)
{
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/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 @@
-
-
-
-
+
+
+
+
+
+
+
+
-
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 9dbaf2193..d77bc2bac 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;
@@ -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,104 @@ 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);
+ 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;
+ }
+
+ 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 +1038,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 +1077,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;
}
diff --git a/Barotrauma/BarotraumaShared/Source/Characters/Character.cs b/Barotrauma/BarotraumaShared/Source/Characters/Character.cs
index 6819a412f..ad03fcce7 100644
--- a/Barotrauma/BarotraumaShared/Source/Characters/Character.cs
+++ b/Barotrauma/BarotraumaShared/Source/Characters/Character.cs
@@ -1383,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();
}
@@ -1541,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))
{
@@ -1573,24 +1589,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);
- 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);
@@ -1630,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()
diff --git a/Barotrauma/BarotraumaShared/Source/Characters/CharacterNetworking.cs b/Barotrauma/BarotraumaShared/Source/Characters/CharacterNetworking.cs
index 1a6ec6b07..0420bbab4 100644
--- a/Barotrauma/BarotraumaShared/Source/Characters/CharacterNetworking.cs
+++ b/Barotrauma/BarotraumaShared/Source/Characters/CharacterNetworking.cs
@@ -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);
}
}
diff --git a/Barotrauma/BarotraumaShared/Source/Map/Structure.cs b/Barotrauma/BarotraumaShared/Source/Map/Structure.cs
index 6e2622276..beb737fb9 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;
diff --git a/Barotrauma/BarotraumaShared/Source/Networking/GameServerSettings.cs b/Barotrauma/BarotraumaShared/Source/Networking/GameServerSettings.cs
index e1b103cd4..43e9ad779 100644
--- a/Barotrauma/BarotraumaShared/Source/Networking/GameServerSettings.cs
+++ b/Barotrauma/BarotraumaShared/Source/Networking/GameServerSettings.cs
@@ -133,6 +133,13 @@ namespace Barotrauma.Networking
private set;
}
+ [Serialize(true, true)]
+ public bool AllowRagdollButton
+ {
+ get;
+ private set;
+ }
+
[Serialize(true, true)]
public bool AllowFileTransfers
{
@@ -213,6 +220,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
{
diff --git a/Barotrauma/BarotraumaShared/serversettings.xml b/Barotrauma/BarotraumaShared/serversettings.xml
index 1eb8f2d21..18abd505a 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="False"
SubSelection="Manual"
ModeSelection="Manual"
TraitorsEnabled="No"