using Microsoft.Xna.Framework; using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Barotrauma { class AIObjectiveCombat : AIObjective { const float CoolDown = 10.0f; private Character enemy; private AIObjectiveFindSafety escapeObjective; float coolDownTimer; private readonly float enemyStrength; public AIObjectiveCombat (Character character, Character enemy) : base(character, "") { this.enemy = enemy; foreach (Limb limb in enemy.AnimController.Limbs) { if (limb.attack == null) continue; enemyStrength += limb.attack.GetDamage(1.0f); } coolDownTimer = CoolDown; } protected override void Act(float deltaTime) { coolDownTimer -= deltaTime; var weapon = character.Inventory.FindItem("weapon"); if (weapon==null) { Escape(deltaTime); } else { if (!character.SelectedItems.Contains(weapon)) { character.Inventory.TryPutItem(weapon, 3, false); weapon.Equip(character); } character.CursorPosition = enemy.Position; character.SetInput(InputType.Aim, false, true); Vector2 enemyDiff = Vector2.Normalize(enemy.Position - character.Position); float weaponAngle = ((weapon.body.Dir == 1.0f) ? weapon.body.Rotation : weapon.body.Rotation - MathHelper.Pi); Vector2 weaponDir = new Vector2((float)Math.Cos(weaponAngle), (float)Math.Sin(weaponAngle)); if (Vector2.Dot(enemyDiff, weaponDir)<0.9f) return; List ignoredBodies = new List(); foreach (Limb limb in character.AnimController.Limbs) { ignoredBodies.Add(limb.body.FarseerBody); } var pickedBody = Submarine.PickBody(character.SimPosition, enemy.SimPosition, ignoredBodies); if (pickedBody != null && pickedBody.UserData as Limb == null) return; weapon.Use(deltaTime, character); } } private void Escape(float deltaTime) { if (escapeObjective == null) { escapeObjective = new AIObjectiveFindSafety(character); } if (enemy.AnimController.CurrentHull == character.AnimController.CurrentHull) { escapeObjective.OverrideCurrentHullSafety = 0.0f; } else { escapeObjective.OverrideCurrentHullSafety = null; } escapeObjective.TryComplete(deltaTime); if (Vector2.Distance(character.SimPosition, enemy.SimPosition) < 3.0f) { character.AIController.SteeringManager.SteeringManual(deltaTime, (character.SimPosition - enemy.SimPosition)*0.1f); coolDownTimer = CoolDown; } } public override bool IsCompleted() { return enemy.IsDead || coolDownTimer <= 0.0f; } public override float GetPriority(Character character) { //clamp the strength to the health of this character //(it doesn't make a difference whether the enemy does 200 or 600 damage, it's one hit kill anyway) float enemyDanger = Math.Min(enemyStrength, character.Health) + enemy.Health / 10.0f; EnemyAIController enemyAI = enemy.AIController as EnemyAIController; if (enemyAI != null) { if (enemyAI.SelectedAiTarget == character.AiTarget) enemyDanger *= 2.0f; } return Math.Max(enemyDanger, 30.0f); } public override bool IsDuplicate(AIObjective otherObjective) { AIObjectiveCombat objective = otherObjective as AIObjectiveCombat; if (objective == null) return false; return objective.enemy == enemy; } } }