Human AI improvements, minor UI tweaking
This commit is contained in:
@@ -11,14 +11,23 @@ namespace Barotrauma
|
||||
|
||||
protected float priority;
|
||||
|
||||
protected Character character;
|
||||
|
||||
public virtual bool IsCompleted()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public AIObjective()
|
||||
public virtual bool CanBeCompleted
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
public AIObjective(Character character)
|
||||
{
|
||||
subObjectives = new List<AIObjective>();
|
||||
|
||||
this.character = character;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -26,20 +35,20 @@ namespace Barotrauma
|
||||
/// need to be completed before this one
|
||||
/// </summary>
|
||||
/// <param name="character">the character who's trying to achieve the objective</param>
|
||||
public void TryComplete(float deltaTime, Character character)
|
||||
public void TryComplete(float deltaTime)
|
||||
{
|
||||
foreach (AIObjective objective in subObjectives)
|
||||
{
|
||||
if (objective.IsCompleted()) continue;
|
||||
|
||||
objective.TryComplete(deltaTime, character);
|
||||
objective.TryComplete(deltaTime);
|
||||
return;
|
||||
}
|
||||
|
||||
Act(deltaTime, character);
|
||||
Act(deltaTime);
|
||||
}
|
||||
|
||||
protected virtual void Act(float deltaTime, Character character) { }
|
||||
protected virtual void Act(float deltaTime) { }
|
||||
|
||||
public virtual float GetPriority(Character character)
|
||||
{
|
||||
@@ -48,7 +57,7 @@ namespace Barotrauma
|
||||
|
||||
public virtual bool IsDuplicate(AIObjective otherObjective)
|
||||
{
|
||||
return true;
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,16 +12,26 @@ namespace Barotrauma
|
||||
const float MinSafety = 50.0f;
|
||||
|
||||
AIObjectiveGoTo gotoObjective;
|
||||
|
||||
private List<AITarget> unreachable;
|
||||
|
||||
float currenthullSafety;
|
||||
|
||||
float searchHullTimer;
|
||||
|
||||
protected override void Act(float deltaTime, Character character)
|
||||
public AIObjectiveFindSafety(Character character)
|
||||
: base(character)
|
||||
{
|
||||
unreachable = new List<AITarget>();
|
||||
}
|
||||
|
||||
protected override void Act(float deltaTime)
|
||||
{
|
||||
if (character.AnimController.CurrentHull == null || GetHullSafety(character.AnimController.CurrentHull) > MinSafety)
|
||||
{
|
||||
character.AIController.SteeringManager.SteeringSeek(character.AnimController.CurrentHull.Position);
|
||||
character.AIController.SteeringManager.SteeringSeek(character.AnimController.CurrentHull.SimPosition);
|
||||
|
||||
character.AIController.SelectTarget(null);
|
||||
|
||||
gotoObjective = null;
|
||||
return;
|
||||
@@ -32,34 +42,56 @@ namespace Barotrauma
|
||||
searchHullTimer -= deltaTime;
|
||||
return;
|
||||
}
|
||||
|
||||
searchHullTimer = SearchHullInterval;
|
||||
|
||||
Hull bestHull = null;
|
||||
float bestValue = currenthullSafety;
|
||||
|
||||
foreach (Hull hull in Hull.hullList)
|
||||
else
|
||||
{
|
||||
if (hull == character.AnimController.CurrentHull) continue;
|
||||
|
||||
float hullValue = GetHullSafety(hull);
|
||||
hullValue -= (float)Math.Sqrt(Math.Abs(character.Position.X- hull.Position.X));
|
||||
hullValue -= (float)Math.Sqrt(Math.Abs(character.Position.Y - hull.Position.Y)*2.0f);
|
||||
Hull bestHull = null;
|
||||
float bestValue = currenthullSafety;
|
||||
|
||||
if (bestHull==null || hullValue > bestValue)
|
||||
foreach (Hull hull in Hull.hullList)
|
||||
{
|
||||
bestHull = hull;
|
||||
bestValue = hullValue;
|
||||
if (hull == character.AnimController.CurrentHull) continue;
|
||||
if (unreachable.Contains(hull.AiTarget)) continue;
|
||||
|
||||
float hullValue = GetHullSafety(hull);
|
||||
hullValue -= (float)Math.Sqrt(Math.Abs(character.Position.X- hull.Position.X));
|
||||
hullValue -= (float)Math.Sqrt(Math.Abs(character.Position.Y - hull.Position.Y)*2.0f);
|
||||
|
||||
if (bestHull==null || hullValue > bestValue)
|
||||
{
|
||||
bestHull = hull;
|
||||
bestValue = hullValue;
|
||||
}
|
||||
}
|
||||
|
||||
if (bestHull != null)
|
||||
{
|
||||
gotoObjective = new AIObjectiveGoTo(bestHull.AiTarget, character);
|
||||
//character.AIController.SelectTarget(bestHull.AiTarget);
|
||||
}
|
||||
|
||||
|
||||
searchHullTimer = SearchHullInterval;
|
||||
}
|
||||
|
||||
if (gotoObjective != null)
|
||||
{
|
||||
var pathSteering = character.AIController.SteeringManager as IndoorsSteeringManager;
|
||||
if (pathSteering!=null && pathSteering.CurrentPath!= null &&
|
||||
pathSteering.CurrentPath.Unreachable && !unreachable.Contains(gotoObjective.Target))
|
||||
{
|
||||
unreachable.Add(gotoObjective.Target);
|
||||
}
|
||||
}
|
||||
|
||||
if (bestHull != null)
|
||||
{
|
||||
gotoObjective = new AIObjectiveGoTo(bestHull.AiTarget, character);
|
||||
//character.AIController.SelectTarget(bestHull.AiTarget);
|
||||
}
|
||||
|
||||
gotoObjective.TryComplete(deltaTime, character);
|
||||
|
||||
gotoObjective.TryComplete(deltaTime);
|
||||
}
|
||||
|
||||
public override bool IsDuplicate(AIObjective otherObjective)
|
||||
{
|
||||
return (otherObjective is AIObjectiveFindSafety);
|
||||
}
|
||||
|
||||
public override float GetPriority(Character character)
|
||||
@@ -77,10 +109,11 @@ namespace Barotrauma
|
||||
|
||||
foreach (FireSource fireSource in hull.FireSources)
|
||||
{
|
||||
fireAmount += fireSource.Size.X;
|
||||
fireAmount += Math.Max(fireSource.Size.X,50.0f);
|
||||
}
|
||||
|
||||
float safety = 100.0f - fireAmount - waterPercentage;
|
||||
float safety = 100.0f - fireAmount;
|
||||
if (waterPercentage > 30.0f) safety -= waterPercentage;
|
||||
if (hull.OxygenPercentage < 30.0f) safety -= (30.0f-hull.OxygenPercentage)*3.0f;
|
||||
|
||||
return safety;
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
class AIObjectiveFixLeak : AIObjective
|
||||
{
|
||||
Gap leak;
|
||||
|
||||
public AIObjectiveFixLeak(Gap leak, Character character)
|
||||
:base (character)
|
||||
{
|
||||
this.leak = leak;
|
||||
}
|
||||
|
||||
public override float GetPriority(Character character)
|
||||
{
|
||||
return leak.isHorizontal ? leak.Rect.Height * leak.Open : leak.Rect.Width * leak.Open;
|
||||
}
|
||||
|
||||
public override bool IsDuplicate(AIObjective otherObjective)
|
||||
{
|
||||
AIObjectiveFixLeak fixLeak = otherObjective as AIObjectiveFixLeak;
|
||||
if (fixLeak == null) return false;
|
||||
return fixLeak.leak == leak;
|
||||
}
|
||||
|
||||
protected override void Act(float deltaTime)
|
||||
{
|
||||
var weldingTool = character.Inventory.FindItem("Welding Tool");
|
||||
|
||||
if (weldingTool == null)
|
||||
{
|
||||
subObjectives.Add(new AIObjectiveGetItem(character, "Welding Tool"));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Vector2.Distance(character.Position, leak.Position)>10.0f)
|
||||
{
|
||||
subObjectives.Add(new AIObjectiveGoTo(leak.Position,character));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
class AIObjectiveGetItem : AIObjective
|
||||
{
|
||||
private string itemName;
|
||||
|
||||
private Item targetItem;
|
||||
|
||||
private int currSearchIndex;
|
||||
|
||||
private bool canBeCompleted;
|
||||
|
||||
public override bool CanBeCompleted
|
||||
{
|
||||
get { return canBeCompleted; }
|
||||
}
|
||||
|
||||
public AIObjectiveGetItem(Character character, string itemName)
|
||||
: base (character)
|
||||
{
|
||||
canBeCompleted = true;
|
||||
|
||||
currSearchIndex = 0;
|
||||
|
||||
this.itemName = itemName;
|
||||
}
|
||||
|
||||
protected override void Act(float deltaTime)
|
||||
{
|
||||
if (targetItem != null)
|
||||
{
|
||||
if (Vector2.Distance(character.SimPosition, targetItem.SimPosition) < targetItem.PickDistance)
|
||||
{
|
||||
targetItem.Pick(character, false, true);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (currSearchIndex >= Item.ItemList.Count)
|
||||
{
|
||||
canBeCompleted = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (Item.ItemList[currSearchIndex].HasTag(itemName) || Item.ItemList[currSearchIndex].Name == itemName)
|
||||
{
|
||||
targetItem = Item.ItemList[currSearchIndex];
|
||||
|
||||
while (targetItem.container != null)
|
||||
{
|
||||
targetItem = targetItem.container;
|
||||
}
|
||||
|
||||
subObjectives.Add(new AIObjectiveGoTo(targetItem.Position, character));
|
||||
}
|
||||
|
||||
currSearchIndex++;
|
||||
}
|
||||
|
||||
public override bool IsDuplicate(AIObjective otherObjective)
|
||||
{
|
||||
AIObjectiveGetItem getItem = otherObjective as AIObjectiveGetItem;
|
||||
if (getItem == null) return false;
|
||||
return (getItem.itemName == itemName);
|
||||
}
|
||||
|
||||
public override bool IsCompleted()
|
||||
{
|
||||
return character.Inventory.Items.FirstOrDefault(i => i != null && (i.HasTag(itemName) || i.Name == itemName)) != null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12,22 +12,46 @@ namespace Barotrauma
|
||||
{
|
||||
AITarget target;
|
||||
|
||||
private Character character;
|
||||
Vector2 targetPos;
|
||||
|
||||
public AIObjectiveGoTo(AITarget target, Character character)
|
||||
public override bool CanBeCompleted
|
||||
{
|
||||
this.character = character;
|
||||
this.target = target;
|
||||
|
||||
get
|
||||
{
|
||||
var pathSteering = character.AIController.SteeringManager as IndoorsSteeringManager;
|
||||
return (pathSteering.CurrentPath == null || !pathSteering.CurrentPath.Unreachable);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Act(float deltaTime, Character character)
|
||||
public AITarget Target
|
||||
{
|
||||
if (target == null) return;
|
||||
get { return target; }
|
||||
}
|
||||
|
||||
public AIObjectiveGoTo(AITarget target, Character character)
|
||||
: base (character)
|
||||
{
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
|
||||
public AIObjectiveGoTo(Vector2 targetPos, Character character)
|
||||
: base(character)
|
||||
{
|
||||
this.targetPos = targetPos;
|
||||
}
|
||||
|
||||
protected override void Act(float deltaTime)
|
||||
{
|
||||
character.AIController.SelectTarget(target);
|
||||
|
||||
character.AIController.SteeringManager.SteeringSeek(ConvertUnits.ToDisplayUnits(target.Position));
|
||||
character.AIController.SteeringManager.SteeringSeek(
|
||||
target != null ? target.SimPosition : targetPos);
|
||||
}
|
||||
|
||||
public override bool IsCompleted()
|
||||
{
|
||||
return Vector2.Distance(target != null ? target.SimPosition : ConvertUnits.ToDisplayUnits(targetPos), character.SimPosition) < 0.5f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
class AIObjectiveIdle : AIObjective
|
||||
{
|
||||
AITarget currentTarget;
|
||||
private float newTargetTimer;
|
||||
|
||||
|
||||
|
||||
public AIObjectiveIdle(Character character) : base(character)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public override float GetPriority(Character character)
|
||||
{
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
|
||||
protected override void Act(float deltaTime)
|
||||
{
|
||||
if (newTargetTimer <= 0.0f)
|
||||
{
|
||||
currentTarget = FindRandomTarget();
|
||||
|
||||
newTargetTimer = currentTarget == null ? 5.0f : 10.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
newTargetTimer -= deltaTime;
|
||||
}
|
||||
|
||||
|
||||
if (currentTarget == null) return;
|
||||
|
||||
character.AIController.SteeringManager.SteeringSeek(currentTarget.SimPosition);
|
||||
|
||||
var pathSteering = character.AIController.SteeringManager as IndoorsSteeringManager;
|
||||
if (pathSteering!=null && pathSteering.CurrentPath != null)
|
||||
{
|
||||
if (pathSteering.CurrentPath.NextNode==null || pathSteering.CurrentPath.Unreachable)
|
||||
{
|
||||
character.AIController.SteeringManager.SteeringWander(1.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private AITarget FindRandomTarget()
|
||||
{
|
||||
if (Rand.Int(5)==1)
|
||||
{
|
||||
var idCard = character.Inventory.FindItem("ID Card");
|
||||
if (idCard==null) return null;
|
||||
|
||||
foreach (WayPoint wp in WayPoint.WayPointList)
|
||||
{
|
||||
if (wp.SpawnType != SpawnType.Human) continue;
|
||||
|
||||
foreach (string tag in wp.IdCardTags)
|
||||
{
|
||||
if (idCard.HasTag(tag)) return wp.CurrentHull.AiTarget;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
List<Hull> targetHulls = new List<Hull>(Hull.hullList);
|
||||
//ignore all hulls with fires or water in them
|
||||
targetHulls.RemoveAll(h => h.FireSources.Any() || (h.Volume/h.FullVolume)>0.1f);
|
||||
if (!targetHulls.Any()) return null;
|
||||
|
||||
return targetHulls[Rand.Range(0, targetHulls.Count)].AiTarget;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public override bool IsDuplicate(AIObjective otherObjective)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,14 @@ namespace Barotrauma
|
||||
private List<AIObjective> objectives;
|
||||
|
||||
private Character character;
|
||||
|
||||
public AIObjective CurrentObjective
|
||||
{
|
||||
get
|
||||
{
|
||||
return objectives.Any() ? objectives[0] : null;
|
||||
}
|
||||
}
|
||||
|
||||
public AIObjectiveManager(Character character)
|
||||
{
|
||||
@@ -33,14 +41,24 @@ namespace Barotrauma
|
||||
objectives = objectives.FindAll(o => !o.IsCompleted());
|
||||
|
||||
//sort objectives according to priority
|
||||
objectives.Sort((x, y) => x.GetPriority(character).CompareTo(y.GetPriority(character)));
|
||||
|
||||
objectives.Sort((x, y) => y.GetPriority(character).CompareTo(x.GetPriority(character)));
|
||||
|
||||
if (character.AnimController.CurrentHull!=null)
|
||||
{
|
||||
var gaps = character.AnimController.CurrentHull.FindGaps();
|
||||
|
||||
foreach (Gap gap in gaps)
|
||||
{
|
||||
if (gap.linkedTo.Count > 1) continue;
|
||||
AddObjective(new AIObjectiveFixLeak(gap, character));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void DoCurrentObjective(float deltaTime)
|
||||
{
|
||||
if (!objectives.Any()) return;
|
||||
objectives[0].TryComplete(deltaTime, character);
|
||||
objectives[0].TryComplete(deltaTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,12 +9,13 @@ namespace Barotrauma
|
||||
{
|
||||
private Item targetItem;
|
||||
|
||||
public AIObjectiveOperateItem(Item item)
|
||||
public AIObjectiveOperateItem(Item item, Character character)
|
||||
:base (character)
|
||||
{
|
||||
targetItem = item;
|
||||
}
|
||||
|
||||
protected override void Act(float deltaTime, Character character)
|
||||
protected override void Act(float deltaTime)
|
||||
{
|
||||
//item.AIOperate(float deltaTime, Character character) or something
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user