From a272d22de8288e5cc20b72448c567fb019d69eaa Mon Sep 17 00:00:00 2001 From: juanjp600 Date: Wed, 6 Dec 2017 17:57:58 -0300 Subject: [PATCH] Players can now pick up corpses to eat them --- .../Source/Characters/CharacterHUD.cs | 4 +- .../Animation/FishAnimController.cs | 75 +++++++++++++++++++ .../Source/Characters/Character.cs | 27 +++---- 3 files changed, 91 insertions(+), 15 deletions(-) diff --git a/Barotrauma/BarotraumaClient/Source/Characters/CharacterHUD.cs b/Barotrauma/BarotraumaClient/Source/Characters/CharacterHUD.cs index f5d37e0b2..a9f4d0dee 100644 --- a/Barotrauma/BarotraumaClient/Source/Characters/CharacterHUD.cs +++ b/Barotrauma/BarotraumaClient/Source/Characters/CharacterHUD.cs @@ -114,7 +114,7 @@ namespace Barotrauma } } - if (character.SelectedCharacter != null && character.SelectedCharacter.Inventory != null) + if (character.IsHumanoid && character.SelectedCharacter != null && character.SelectedCharacter.Inventory != null) { character.SelectedCharacter.Inventory.Update(deltaTime); } @@ -164,7 +164,7 @@ namespace Barotrauma character.Inventory.DrawOwn(spriteBatch); } - if (character.SelectedCharacter != null && character.SelectedCharacter.Inventory != null) + if (character.IsHumanoid && character.SelectedCharacter != null && character.SelectedCharacter.Inventory != null) { character.SelectedCharacter.Inventory.DrawOffset = new Vector2(320.0f, 0.0f); character.SelectedCharacter.Inventory.DrawOwn(spriteBatch); diff --git a/Barotrauma/BarotraumaShared/Source/Characters/Animation/FishAnimController.cs b/Barotrauma/BarotraumaShared/Source/Characters/Animation/FishAnimController.cs index 31a73d3fb..af427b259 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/Animation/FishAnimController.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/Animation/FishAnimController.cs @@ -154,6 +154,8 @@ namespace Barotrauma } } + if (character.SelectedCharacter != null) DragCharacter(character.SelectedCharacter); + if (!flip) return; flipTimer += deltaTime; @@ -169,6 +171,79 @@ namespace Barotrauma } } + private float eatTimer = 0.0f; + + public override void DragCharacter(Character target) + { + if (target == null) return; + + Limb mouthLimb = Array.Find(Limbs, l => l != null && l.MouthPos.HasValue); + if (mouthLimb == null) mouthLimb = GetLimb(LimbType.Head); + + if (mouthLimb == null) + { + DebugConsole.ThrowError("Character \"" + character.SpeciesName + "\" failed to eat a target (a head or a limb with a mouthpos required)"); + return; + } + + Character targetCharacter = target; + float eatSpeed = character.Mass / targetCharacter.Mass * 0.1f; + + eatTimer += (float)Timing.Step * eatSpeed; + + Vector2 mouthPos = mouthLimb.SimPosition; + if (mouthLimb.MouthPos.HasValue) + { + float cos = (float)Math.Cos(mouthLimb.Rotation); + float sin = (float)Math.Sin(mouthLimb.Rotation); + + mouthPos += new Vector2( + mouthLimb.MouthPos.Value.X * cos - mouthLimb.MouthPos.Value.Y * sin, + mouthLimb.MouthPos.Value.X * sin + mouthLimb.MouthPos.Value.Y * cos); + } + + Vector2 attackSimPosition = character.Submarine == null ? ConvertUnits.ToSimUnits(target.WorldPosition) : target.SimPosition; + + Vector2 limbDiff = attackSimPosition - mouthPos; + float limbDist = limbDiff.Length(); + if (limbDist < 1.0f) + { + //pull the target character to the position of the mouth + //(+ make the force fluctuate to waggle the character a bit) + targetCharacter.AnimController.MainLimb.MoveToPos(mouthPos, (float)(Math.Sin(eatTimer) + 10.0f)); + targetCharacter.AnimController.MainLimb.body.SmoothRotate(mouthLimb.Rotation); + targetCharacter.AnimController.Collider.MoveToPos(mouthPos, (float)(Math.Sin(eatTimer) + 10.0f)); + + //pull the character's mouth to the target character (again with a fluctuating force) + float pullStrength = (float)(Math.Sin(eatTimer) * Math.Max(Math.Sin(eatTimer * 0.5f), 0.0f)); + mouthLimb.body.ApplyForce(limbDiff * mouthLimb.Mass * 50.0f * pullStrength); + + if (eatTimer % 1.0f < 0.5f && (eatTimer - (float)Timing.Step * eatSpeed) % 1.0f > 0.5f) + { + //apply damage to the target character to get some blood particles flying + targetCharacter.AnimController.MainLimb.AddDamage(targetCharacter.SimPosition, DamageType.None, Rand.Range(10.0f, 25.0f), 10.0f, false); + + //keep severing joints until there is only one limb left + LimbJoint[] nonSeveredJoints = Array.FindAll(targetCharacter.AnimController.LimbJoints, l => !l.IsSevered && l.CanBeSevered); + if (nonSeveredJoints.Length == 0) + { + //only one limb left, the character is now full eaten + Entity.Spawner.AddToRemoveQueue(targetCharacter); + character.SelectedCharacter = null; + character.Health += 10.0f; + } + else //sever a random joint + { + targetCharacter.AnimController.SeverLimbJoint(nonSeveredJoints[Rand.Int(nonSeveredJoints.Length)]); + } + } + } + else + { + character.SelectedCharacter = null; + } + } + void UpdateSineAnim(float deltaTime) { movement = TargetMovement*swimSpeed; diff --git a/Barotrauma/BarotraumaShared/Source/Characters/Character.cs b/Barotrauma/BarotraumaShared/Source/Characters/Character.cs index d78e6061f..c0f415aa9 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/Character.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/Character.cs @@ -175,7 +175,7 @@ namespace Barotrauma { get { return !IsUnconscious && Stun <= 0.0f && !isDead; } } - + public bool CanInteract { get { return AllowInput && IsHumanoid && !LockHands; } @@ -206,6 +206,7 @@ namespace Barotrauma get { return selectedCharacter; } set { + if (value == selectedCharacter) return; if (selectedCharacter != null) selectedCharacter.selectedBy = null; selectedCharacter = value; @@ -1030,7 +1031,7 @@ namespace Barotrauma public bool CanInteractWith(Character c, float maxDist = 200.0f) { - if (c == this || !c.Enabled || c.info == null || !c.IsHumanoid || !c.CanBeSelected) return false; + if (c == this || !c.Enabled || !c.CanBeSelected) return false; maxDist = ConvertUnits.ToSimUnits(maxDist); if (Vector2.DistanceSquared(SimPosition, c.SimPosition) > maxDist * maxDist) return false; @@ -1242,7 +1243,7 @@ namespace Barotrauma public void SelectCharacter(Character character) { if (character == null) return; - + SelectedCharacter = character; } @@ -1264,27 +1265,27 @@ namespace Barotrauma public void DoInteractionUpdate(float deltaTime, Vector2 mouseSimPos) { bool isLocalPlayer = (controlled == this); - if (!isLocalPlayer && (this is AICharacter || !IsRemotePlayer)) + if (!isLocalPlayer && (this is AICharacter && !IsRemotePlayer)) { return; } if (!CanInteract) { - if (SelectedCharacter != null) - { - DeselectCharacter(); - } selectedConstruction = null; focusedItem = null; - focusedCharacter = null; - return; + if (!AllowInput) + { + focusedCharacter = null; + if (SelectedCharacter != null) DeselectCharacter(); + return; + } } if ((!isLocalPlayer && IsKeyHit(InputType.Select) && GameMain.Server == null) || (isLocalPlayer && (findFocusedTimer <= 0.0f || Screen.Selected == GameMain.SubEditorScreen))) { focusedCharacter = FindCharacterAtPosition(mouseSimPos); - focusedItem = FindItemAtPosition(mouseSimPos, AnimController.InWater ? 0.5f : 0.25f); + focusedItem = CanInteract ? FindItemAtPosition(mouseSimPos, AnimController.InWater ? 0.5f : 0.25f) : null; if (focusedCharacter != null && focusedItem != null) { @@ -1303,7 +1304,7 @@ namespace Barotrauma { findFocusedTimer -= deltaTime; } - + if (SelectedCharacter != null && IsKeyHit(InputType.Select)) { DeselectCharacter(); @@ -1471,7 +1472,7 @@ namespace Barotrauma if (IsRagdolled) { - ((HumanoidAnimController)AnimController).Crouching = false; + if (AnimController is HumanoidAnimController) ((HumanoidAnimController)AnimController).Crouching = false; AnimController.ResetPullJoints(); selectedConstruction = null;