Merge pull request #101 from Crystalwarrior/moRags

Body shoulder-grab, better CPR anims, CPR and Crit overhaul!
This commit is contained in:
Joonas Rikkonen
2017-12-20 19:37:38 +02:00
committed by GitHub
11 changed files with 370 additions and 64 deletions

View File

@@ -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)

View File

@@ -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)
{

View File

@@ -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

View File

@@ -14,13 +14,16 @@
<RequiredItems name="Battery Cell" type="Contained"/>
</WifiComponent>
<ItemContainer capacity="1" hideitems="true">
<Containable name="Battery Cell"/>
<Containable name="Fulgurium Battery Cell"/>
</ItemContainer>
<ItemContainer capacity="1" hideitems="true">
<Containable name="Battery Cell">
<StatusEffect type="OnContaining" target="Contained" Condition="-0.05"/>
</Containable>
<Containable name="Fulgurium Battery Cell">
<StatusEffect type="OnContaining" target="Contained" Condition="-0.05"/>
</Containable>
</ItemContainer>
<Wearable limbtype="Head" slots="Any,Face">
<StatusEffect type="OnWearing" target="Contained" Condition="-0.1"/>
<sprite texture="headset.png" limb="Head" origin="0.5,0.5"/>
</Wearable>
</Item>

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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()

View 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);
}
}

View File

@@ -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;

View File

@@ -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
{

View File

@@ -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"