diff --git a/Barotrauma/Content/Characters/Crawler/crawler.xml b/Barotrauma/Content/Characters/Crawler/crawler.xml index aaf2c1588..a1b1b7cf3 100644 --- a/Barotrauma/Content/Characters/Crawler/crawler.xml +++ b/Barotrauma/Content/Characters/Crawler/crawler.xml @@ -12,6 +12,7 @@ attackpriorityrooms="50.0" attackpriorityweaker="50" attackprioritystronger="-60" + eatpriority="55" sight="0.5" hearing="1.0" fleehealththreshold="10" @@ -28,7 +29,7 @@ - + diff --git a/Barotrauma/Content/Characters/Mantis/mantis.png b/Barotrauma/Content/Characters/Mantis/mantis.png index b0b287343..a8a6618e6 100644 Binary files a/Barotrauma/Content/Characters/Mantis/mantis.png and b/Barotrauma/Content/Characters/Mantis/mantis.png differ diff --git a/Barotrauma/Content/Characters/Mantis/mantis.xml b/Barotrauma/Content/Characters/Mantis/mantis.xml index 419f3a6f4..40099b750 100644 --- a/Barotrauma/Content/Characters/Mantis/mantis.xml +++ b/Barotrauma/Content/Characters/Mantis/mantis.xml @@ -32,7 +32,7 @@ - + @@ -48,7 +48,7 @@ - + @@ -87,7 +87,7 @@ - + diff --git a/Barotrauma/Content/Characters/Tigerthresher/tigerthresher.xml b/Barotrauma/Content/Characters/Tigerthresher/tigerthresher.xml index d63595917..fe6767a6a 100644 --- a/Barotrauma/Content/Characters/Tigerthresher/tigerthresher.xml +++ b/Barotrauma/Content/Characters/Tigerthresher/tigerthresher.xml @@ -11,6 +11,7 @@ attackpriorityrooms="50.0" attackpriorityweaker="50" attackprioritystronger="-30" + eatpriority="55" sight="0.5" hearing="1.0"/> @@ -21,7 +22,7 @@ - + diff --git a/Barotrauma/Source/Characters/AI/EnemyAIController.cs b/Barotrauma/Source/Characters/AI/EnemyAIController.cs index 05138ced0..fb1a53a11 100644 --- a/Barotrauma/Source/Characters/AI/EnemyAIController.cs +++ b/Barotrauma/Source/Characters/AI/EnemyAIController.cs @@ -53,6 +53,8 @@ namespace Barotrauma private AITarget selectedAiTarget; private AITargetMemory selectedTargetMemory; private float targetValue; + + private float eatTimer; private Dictionary targetMemories; @@ -150,7 +152,11 @@ namespace Barotrauma } else if ((selectedAiTarget.Entity is Character) && ((Character)selectedAiTarget.Entity).IsDead) { - state = AIState.Eat; + if (state != AIState.Eat) + { + eatTimer = 0.0f; + state = AIState.Eat; + } } else { @@ -420,7 +426,7 @@ namespace Barotrauma private void UpdateEating(float deltaTime) { - if (selectedAiTarget == null) + if (selectedAiTarget == null || selectedAiTarget.Entity == null || selectedAiTarget.Entity.Removed) { state = AIState.None; return; @@ -428,7 +434,7 @@ namespace Barotrauma Limb mouthLimb = Array.Find(Character.AnimController.Limbs, l => l != null && l.MouthPos.HasValue); if (mouthLimb == null) mouthLimb = Character.AnimController.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)"); @@ -436,6 +442,11 @@ namespace Barotrauma return; } + Character targetCharacter = selectedAiTarget.Entity as Character; + float eatSpeed = Character.Mass / targetCharacter.Mass * 0.1f; + + eatTimer += deltaTime * eatSpeed; + Vector2 mouthPos = mouthLimb.SimPosition; if (mouthLimb.MouthPos.HasValue) { @@ -447,37 +458,49 @@ namespace Barotrauma mouthLimb.MouthPos.Value.X * sin + mouthLimb.MouthPos.Value.Y * cos); } - Vector2 attackSimPosition = Character.Submarine == null ? ConvertUnits.ToSimUnits(selectedAiTarget.WorldPosition) : selectedAiTarget.SimPosition; - steeringManager.SteeringSeek(attackSimPosition + (mouthPos - SimPosition), 3); + Vector2 limbDiff = attackSimPosition - mouthPos; float limbDist = limbDiff.Length(); if (limbDist < 1.0f) { - Character targetCharacter = selectedAiTarget.Entity as Character; - //targetCharacter.AnimController.MainLimb.body.ApplyForce(-limbDiff * targetCharacter.AnimController.Mass * (float)(Math.Sin(Timing.TotalTime)+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.MoveToPos( - mouthPos, - (float)(Math.Sin(Timing.TotalTime) + 10.0f)); - steeringManager.SteeringManual(deltaTime, limbDiff); + //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)); + steeringManager.SteeringManual(deltaTime, limbDiff * pullStrength); + mouthLimb.body.ApplyForce(limbDiff * mouthLimb.Mass * 50.0f * pullStrength); - Character.AnimController.Collider.ApplyForce(limbDiff * mouthLimb.Mass * 50.0f, mouthPos); - mouthLimb.body.ApplyForce(limbDiff * mouthLimb.Mass * 50.0f * (float)(Math.Sin(Timing.TotalTime) + 1.0f)); - //eatingLimb.pullJoint.Enabled = true; - //eatingLimb.pullJoint.WorldAnchorB = attackSimPosition; - - if (Rand.Range(0.0f, 60.0f) < 1.0f) + if (eatTimer % 1.0f < 0.5f && (eatTimer - deltaTime * 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); + if (nonSeveredJoints.Length == 0) + { + //only one limb left, the character is now full eaten + Entity.Spawner.AddToRemoveQueue(targetCharacter); + state = AIState.None; + } + else //sever a random joint + { + targetCharacter.AnimController.SeverLimbJoint(nonSeveredJoints[Rand.Int(nonSeveredJoints.Length)]); + } } } else if (limbDist < 2.0f) { steeringManager.SteeringManual(deltaTime, limbDiff); Character.AnimController.Collider.ApplyForce(limbDiff * mouthLimb.Mass * 50.0f, mouthPos); - + } + else + { + steeringManager.SteeringSeek(attackSimPosition + (mouthPos - SimPosition), 3); } }