Human AI with pathfinding and room hazard avoidance
This commit is contained in:
@@ -60,6 +60,10 @@
|
||||
<Compile Include="Source\Characters\AICharacter.cs" />
|
||||
<Compile Include="Source\Characters\AI\AIController.cs" />
|
||||
<Compile Include="Source\Characters\AI\AITarget.cs" />
|
||||
<Compile Include="Source\Characters\AI\HumanAIController.cs" />
|
||||
<Compile Include="Source\Characters\AI\Objectives\AIObjectiveFindSafety.cs" />
|
||||
<Compile Include="Source\Characters\AI\Objectives\AIObjectiveGoTo.cs" />
|
||||
<Compile Include="Source\Characters\AI\Objectives\AIObjectiveManager.cs" />
|
||||
<Compile Include="Source\Characters\AI\Objectives\AIObjectiveOperateItem.cs" />
|
||||
<Compile Include="Source\Characters\AI\Objectives\AIObjective.cs" />
|
||||
<Compile Include="Source\Characters\AI\PathFinder.cs" />
|
||||
|
||||
@@ -16,6 +16,11 @@ namespace Barotrauma
|
||||
|
||||
protected SteeringManager steeringManager;
|
||||
|
||||
public SteeringManager SteeringManager
|
||||
{
|
||||
get { return steeringManager; }
|
||||
}
|
||||
|
||||
public Vector2 Steering
|
||||
{
|
||||
get { return Character.AnimController.TargetMovement; }
|
||||
@@ -41,8 +46,6 @@ namespace Barotrauma
|
||||
public AIController (Character c)
|
||||
{
|
||||
Character = c;
|
||||
|
||||
steeringManager = new SteeringManager(this);
|
||||
}
|
||||
|
||||
public virtual void DebugDraw(SpriteBatch spriteBatch) { }
|
||||
|
||||
@@ -80,6 +80,8 @@ namespace Barotrauma
|
||||
sight = ToolBox.GetAttributeFloat(aiElement, "sight", 0.0f);
|
||||
hearing = ToolBox.GetAttributeFloat(aiElement, "hearing", 0.0f);
|
||||
|
||||
steeringManager = new SteeringManager(this);
|
||||
|
||||
state = AiState.None;
|
||||
}
|
||||
|
||||
|
||||
89
Subsurface/Source/Characters/AI/HumanAIController.cs
Normal file
89
Subsurface/Source/Characters/AI/HumanAIController.cs
Normal file
@@ -0,0 +1,89 @@
|
||||
using FarseerPhysics;
|
||||
using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
class HumanAIController : AIController
|
||||
{
|
||||
const float UpdateObjectiveInterval = 0.5f;
|
||||
|
||||
private AIObjectiveManager objectiveManager;
|
||||
|
||||
private AITarget selectedAiTarget;
|
||||
|
||||
private float updateObjectiveTimer;
|
||||
|
||||
public HumanAIController(Character c) : base(c)
|
||||
{
|
||||
steeringManager = new PathSteeringManager(this);
|
||||
|
||||
objectiveManager = new AIObjectiveManager(c);
|
||||
objectiveManager.AddObjective(new AIObjectiveFindSafety());
|
||||
}
|
||||
|
||||
public override void Update(float deltaTime)
|
||||
{
|
||||
if (updateObjectiveTimer>0.0f)
|
||||
{
|
||||
updateObjectiveTimer -= deltaTime;
|
||||
}
|
||||
else
|
||||
{
|
||||
objectiveManager.UpdateObjectives();
|
||||
updateObjectiveTimer = UpdateObjectiveInterval;
|
||||
}
|
||||
|
||||
objectiveManager.DoCurrentObjective(deltaTime);
|
||||
|
||||
//if (Character.Controlled != null)
|
||||
//{
|
||||
// steeringManager.SteeringSeek(Character.Controlled.Position);
|
||||
//}
|
||||
|
||||
Character.AnimController.IgnorePlatforms = (-Character.AnimController.TargetMovement.Y > Math.Abs(Character.AnimController.TargetMovement.X));
|
||||
|
||||
if (Math.Abs(Character.AnimController.TargetMovement.X)>0.1f)
|
||||
{
|
||||
Character.AnimController.TargetDir = Character.AnimController.TargetMovement.X > 0.0f ? Direction.Right : Direction.Left;
|
||||
}
|
||||
|
||||
steeringManager.Update();
|
||||
}
|
||||
|
||||
public override void SelectTarget(AITarget target)
|
||||
{
|
||||
selectedAiTarget = target;
|
||||
}
|
||||
|
||||
public override void DebugDraw(Microsoft.Xna.Framework.Graphics.SpriteBatch spriteBatch)
|
||||
{
|
||||
|
||||
if (selectedAiTarget != null)
|
||||
{
|
||||
GUI.DrawLine(spriteBatch, new Vector2(Character.Position.X, -Character.Position.Y), ConvertUnits.ToDisplayUnits(new Vector2(selectedAiTarget.Position.X, -selectedAiTarget.Position.Y)), Color.Red);
|
||||
}
|
||||
|
||||
PathSteeringManager pathSteering = steeringManager as PathSteeringManager;
|
||||
if (pathSteering == null || pathSteering.CurrentPath == null || pathSteering.CurrentPath.CurrentNode==null) return;
|
||||
|
||||
GUI.DrawLine(spriteBatch,
|
||||
new Vector2(Character.Position.X, -Character.Position.Y),
|
||||
new Vector2(pathSteering.CurrentPath.CurrentNode.Position.X, -pathSteering.CurrentPath.CurrentNode.Position.Y),
|
||||
Color.LightGreen);
|
||||
|
||||
|
||||
for (int i = 1; i < pathSteering.CurrentPath.Nodes.Count; i++)
|
||||
{
|
||||
GUI.DrawLine(spriteBatch,
|
||||
new Vector2(pathSteering.CurrentPath.Nodes[i].Position.X, -pathSteering.CurrentPath.Nodes[i].Position.Y),
|
||||
new Vector2(pathSteering.CurrentPath.Nodes[i - 1].Position.X, -pathSteering.CurrentPath.Nodes[i-1].Position.Y),
|
||||
Color.LightGreen);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,8 @@ namespace Barotrauma
|
||||
{
|
||||
protected List<AIObjective> subObjectives;
|
||||
|
||||
protected float priority;
|
||||
|
||||
public virtual bool IsCompleted()
|
||||
{
|
||||
return false;
|
||||
@@ -21,7 +23,7 @@ namespace Barotrauma
|
||||
|
||||
/// <summary>
|
||||
/// makes the character act according to the objective, or according to any subobjectives that
|
||||
/// need to be completed before this one (starting from the one with the highest priority)
|
||||
/// 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)
|
||||
@@ -38,5 +40,15 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
protected virtual void Act(float deltaTime, Character character) { }
|
||||
|
||||
public virtual float GetPriority(Character character)
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
public virtual bool IsDuplicate(AIObjective otherObjective)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
class AIObjectiveFindSafety : AIObjective
|
||||
{
|
||||
const float SearchHullInterval = 1.0f;
|
||||
const float MinSafety = 50.0f;
|
||||
|
||||
AIObjectiveGoTo gotoObjective;
|
||||
|
||||
float currenthullSafety;
|
||||
|
||||
float searchHullTimer;
|
||||
|
||||
protected override void Act(float deltaTime, Character character)
|
||||
{
|
||||
if (character.AnimController.CurrentHull == null || GetHullSafety(character.AnimController.CurrentHull) > MinSafety)
|
||||
{
|
||||
character.AIController.SteeringManager.SteeringSeek(character.AnimController.CurrentHull.Position);
|
||||
|
||||
gotoObjective = null;
|
||||
return;
|
||||
}
|
||||
|
||||
if (searchHullTimer>0.0f)
|
||||
{
|
||||
searchHullTimer -= deltaTime;
|
||||
return;
|
||||
}
|
||||
|
||||
searchHullTimer = SearchHullInterval;
|
||||
|
||||
Hull bestHull = null;
|
||||
float bestValue = currenthullSafety;
|
||||
|
||||
foreach (Hull hull in Hull.hullList)
|
||||
{
|
||||
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);
|
||||
|
||||
if (bestHull==null || hullValue > bestValue)
|
||||
{
|
||||
bestHull = hull;
|
||||
bestValue = hullValue;
|
||||
}
|
||||
}
|
||||
|
||||
if (bestHull != null)
|
||||
{
|
||||
gotoObjective = new AIObjectiveGoTo(bestHull.AiTarget, character);
|
||||
//character.AIController.SelectTarget(bestHull.AiTarget);
|
||||
}
|
||||
|
||||
gotoObjective.TryComplete(deltaTime, character);
|
||||
}
|
||||
|
||||
public override float GetPriority(Character character)
|
||||
{
|
||||
if (character.AnimController.CurrentHull == null) return 0.0f;
|
||||
currenthullSafety = GetHullSafety(character.AnimController.CurrentHull);
|
||||
priority = 100.0f - currenthullSafety;
|
||||
return priority;
|
||||
}
|
||||
|
||||
private float GetHullSafety(Hull hull)
|
||||
{
|
||||
float waterPercentage = (hull.Volume / hull.FullVolume)*100.0f;
|
||||
float fireAmount = 0.0f;
|
||||
|
||||
foreach (FireSource fireSource in hull.FireSources)
|
||||
{
|
||||
fireAmount += fireSource.Size.X;
|
||||
}
|
||||
|
||||
float safety = 100.0f - fireAmount - waterPercentage;
|
||||
if (hull.OxygenPercentage < 30.0f) safety -= (30.0f-hull.OxygenPercentage)*3.0f;
|
||||
|
||||
return safety;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
using Barotrauma.Items.Components;
|
||||
using FarseerPhysics;
|
||||
using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
class AIObjectiveGoTo : AIObjective
|
||||
{
|
||||
AITarget target;
|
||||
|
||||
private Character character;
|
||||
|
||||
public AIObjectiveGoTo(AITarget target, Character character)
|
||||
{
|
||||
this.character = character;
|
||||
this.target = target;
|
||||
|
||||
}
|
||||
|
||||
protected override void Act(float deltaTime, Character character)
|
||||
{
|
||||
if (target == null) return;
|
||||
|
||||
character.AIController.SelectTarget(target);
|
||||
|
||||
character.AIController.SteeringManager.SteeringSeek(ConvertUnits.ToDisplayUnits(target.Position));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
class AIObjectiveManager
|
||||
{
|
||||
private List<AIObjective> objectives;
|
||||
|
||||
private Character character;
|
||||
|
||||
public AIObjectiveManager(Character character)
|
||||
{
|
||||
this.character = character;
|
||||
|
||||
objectives = new List<AIObjective>();
|
||||
}
|
||||
|
||||
public void AddObjective(AIObjective objective)
|
||||
{
|
||||
if (objectives.Find(o => o.IsDuplicate(objective)) != null) return;
|
||||
|
||||
objectives.Add(objective);
|
||||
}
|
||||
|
||||
public void UpdateObjectives()
|
||||
{
|
||||
if (!objectives.Any()) return;
|
||||
|
||||
//remove completed objectives
|
||||
objectives = objectives.FindAll(o => !o.IsCompleted());
|
||||
|
||||
//sort objectives according to priority
|
||||
objectives.Sort((x, y) => x.GetPriority(character).CompareTo(y.GetPriority(character)));
|
||||
|
||||
}
|
||||
|
||||
public void DoCurrentObjective(float deltaTime)
|
||||
{
|
||||
if (!objectives.Any()) return;
|
||||
objectives[0].TryComplete(deltaTime, character);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -18,5 +18,13 @@ namespace Barotrauma
|
||||
{
|
||||
//item.AIOperate(float deltaTime, Character character) or something
|
||||
}
|
||||
|
||||
public override bool IsDuplicate(AIObjective otherObjective)
|
||||
{
|
||||
AIObjectiveOperateItem operateItem = otherObjective as AIObjectiveOperateItem;
|
||||
if (operateItem == null) return false;
|
||||
|
||||
return (operateItem.targetItem == targetItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using FarseerPhysics;
|
||||
using Microsoft.Xna.Framework;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
@@ -76,6 +77,9 @@ namespace Barotrauma
|
||||
|
||||
class PathFinder
|
||||
{
|
||||
public delegate float GetNodePenaltyHandler(PathNode node, PathNode prevNode);
|
||||
public GetNodePenaltyHandler GetNodePriority;
|
||||
|
||||
List<PathNode> nodes;
|
||||
|
||||
private bool insideSubmarine;
|
||||
@@ -89,6 +93,9 @@ namespace Barotrauma
|
||||
|
||||
public SteeringPath FindPath(Vector2 start, Vector2 end)
|
||||
{
|
||||
System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
|
||||
sw.Start();
|
||||
|
||||
float closestDist = 0.0f;
|
||||
PathNode startNode = null;
|
||||
foreach (PathNode node in nodes)
|
||||
@@ -96,11 +103,19 @@ namespace Barotrauma
|
||||
float dist = Vector2.Distance(start,node.Position);
|
||||
if (dist<closestDist || startNode==null)
|
||||
{
|
||||
if (insideSubmarine && Submarine.CheckVisibility(start, node.Position) != null) continue;
|
||||
|
||||
closestDist = dist;
|
||||
startNode = node;
|
||||
}
|
||||
}
|
||||
|
||||
if (startNode == null)
|
||||
{
|
||||
DebugConsole.ThrowError("Pathfinding error, couldn't find a start node");
|
||||
return new SteeringPath();
|
||||
}
|
||||
|
||||
closestDist = 0.0f;
|
||||
PathNode endNode = null;
|
||||
foreach (PathNode node in nodes)
|
||||
@@ -108,18 +123,26 @@ namespace Barotrauma
|
||||
float dist = Vector2.Distance(end, node.Position);
|
||||
if (dist < closestDist || endNode == null)
|
||||
{
|
||||
if (insideSubmarine && Submarine.CheckVisibility(end, node.Waypoint.SimPosition) != null) continue;
|
||||
|
||||
closestDist = dist;
|
||||
endNode = node;
|
||||
}
|
||||
}
|
||||
|
||||
if (startNode == null || endNode == null)
|
||||
if (endNode == null)
|
||||
{
|
||||
DebugConsole.ThrowError("Pathfinding error, couldn't find pathnodes");
|
||||
DebugConsole.ThrowError("Pathfinding error, couldn't find an end node");
|
||||
return new SteeringPath();
|
||||
}
|
||||
|
||||
return FindPath(startNode,endNode);
|
||||
|
||||
var path = FindPath(startNode,endNode);
|
||||
|
||||
sw.Stop();
|
||||
System.Diagnostics.Debug.WriteLine("findpath: " + sw.ElapsedTicks);
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
public SteeringPath FindPath(WayPoint start, WayPoint end)
|
||||
@@ -157,7 +180,7 @@ namespace Barotrauma
|
||||
node.G = 0.0f;
|
||||
node.H = 0.0f;
|
||||
}
|
||||
|
||||
|
||||
start.state = 1;
|
||||
while (true)
|
||||
{
|
||||
@@ -185,7 +208,10 @@ namespace Barotrauma
|
||||
//a node that hasn't been searched yet
|
||||
if (nextNode.state==0)
|
||||
{
|
||||
nextNode.H = Vector2.Distance(nextNode.Position,end.Position);
|
||||
nextNode.H = Vector2.DistanceSquared(nextNode.Position,end.Position);
|
||||
|
||||
if (GetNodePriority != null) nextNode.H += GetNodePriority(currNode, nextNode);
|
||||
|
||||
nextNode.G = currNode.G + currNode.distances[i];
|
||||
nextNode.F = nextNode.G + nextNode.H;
|
||||
nextNode.Parent = currNode;
|
||||
|
||||
@@ -4,6 +4,7 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using Microsoft.Xna.Framework;
|
||||
using FarseerPhysics;
|
||||
using Barotrauma.Items.Components;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
@@ -12,13 +13,34 @@ namespace Barotrauma
|
||||
private PathFinder pathFinder;
|
||||
private SteeringPath currentPath;
|
||||
|
||||
private Character character;
|
||||
|
||||
private List<Controller> openableButtons;
|
||||
|
||||
public SteeringPath CurrentPath
|
||||
{
|
||||
get { return currentPath; }
|
||||
}
|
||||
|
||||
public PathFinder PathFinder
|
||||
{
|
||||
get { return pathFinder; }
|
||||
}
|
||||
|
||||
private Vector2 currentTarget;
|
||||
|
||||
private float findPathTimer;
|
||||
|
||||
public PathSteeringManager(ISteerable host)
|
||||
: base(host)
|
||||
{}
|
||||
{
|
||||
pathFinder = new PathFinder(WayPoint.WayPointList.FindAll(wp => wp.SpawnType == SpawnType.Path), true);
|
||||
pathFinder.GetNodePriority = GetNodePriority;
|
||||
|
||||
character = (host as AIController).Character;
|
||||
|
||||
openableButtons = new List<Controller>();
|
||||
}
|
||||
|
||||
public override void Update(float speed = 1)
|
||||
{
|
||||
@@ -36,14 +58,31 @@ namespace Barotrauma
|
||||
if (findPathTimer > 0.0f) return Vector2.Zero;
|
||||
|
||||
currentTarget = target;
|
||||
currentPath = pathFinder.FindPath(ConvertUnits.ToDisplayUnits(host.SimPosition), target);
|
||||
currentPath = pathFinder.FindPath(host.SimPosition, ConvertUnits.ToSimUnits(target));
|
||||
|
||||
findPathTimer = 1.0f;
|
||||
|
||||
return DiffToCurrentNode();
|
||||
}
|
||||
|
||||
|
||||
//if (pathSteering == null || pathSteering.CurrentPath == null || pathSteering.CurrentPath.CurrentNode == null) return;
|
||||
|
||||
//if (currentPath.CurrentNode.ConnectedGap != null && currentPath.CurrentNode.ConnectedGap.Open < 0.9f)
|
||||
//{
|
||||
foreach (Controller controller in openableButtons)
|
||||
{
|
||||
if (Vector2.Distance(controller.Item.SimPosition, character.SimPosition) > controller.Item.PickDistance) continue;
|
||||
|
||||
controller.Item.Pick(character, false, true);
|
||||
}
|
||||
//}
|
||||
|
||||
|
||||
|
||||
Vector2 diff = DiffToCurrentNode();
|
||||
|
||||
if (diff == Vector2.Zero) return -host.Steering;
|
||||
|
||||
return (diff == Vector2.Zero) ? Vector2.Zero : Vector2.Normalize(diff)*speed;
|
||||
}
|
||||
@@ -52,11 +91,61 @@ namespace Barotrauma
|
||||
{
|
||||
if (currentPath == null) return Vector2.Zero;
|
||||
|
||||
currentPath.CheckProgress(host.SimPosition, 0.1f);
|
||||
currentPath.CheckProgress(host.SimPosition, 0.45f);
|
||||
|
||||
if (currentPath.CurrentNode == null) return Vector2.Zero;
|
||||
|
||||
return currentPath.CurrentNode.SimPosition - host.SimPosition;
|
||||
}
|
||||
|
||||
private float GetNodePriority(PathNode node, PathNode nextNode)
|
||||
{
|
||||
if (character==null) return 0.0f;
|
||||
if (nextNode.Waypoint.ConnectedGap!=null)
|
||||
{
|
||||
if (nextNode.Waypoint.ConnectedGap.Open > 0.9f) return 0.0f;
|
||||
if (nextNode.Waypoint.ConnectedGap.ConnectedDoor == null) return 100.0f;
|
||||
|
||||
var doorButtons = GetDoorButtons(nextNode.Waypoint.ConnectedGap.ConnectedDoor);
|
||||
foreach (Controller button in doorButtons)
|
||||
{
|
||||
if (Math.Sign(button.Item.Position.X - nextNode.Waypoint.Position.X) !=
|
||||
Math.Sign(node.Position.X - nextNode.Position.X)) continue;
|
||||
|
||||
if (!button.HasRequiredItems(character, false)) return 1000.0f;
|
||||
}
|
||||
}
|
||||
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
private List<Controller> GetDoorButtons(Door door)
|
||||
{
|
||||
if (door == null) return new List<Controller>();
|
||||
ConnectionPanel connectionPanel = door.Item.GetComponent<ConnectionPanel>();
|
||||
|
||||
List<Controller> doorButtons = new List<Controller>();
|
||||
|
||||
foreach (Connection c in connectionPanel.Connections)
|
||||
{
|
||||
foreach (Wire w in c.Wires)
|
||||
{
|
||||
if (w == null) continue;
|
||||
var otherConnection = w.OtherConnection(c);
|
||||
|
||||
if (otherConnection.Item == door.Item || otherConnection == null) continue;
|
||||
|
||||
var controller = otherConnection.Item.GetComponent<Controller>();
|
||||
if (controller != null)
|
||||
{
|
||||
doorButtons.Add(controller);
|
||||
if (!openableButtons.Contains(controller)) openableButtons.Add(controller);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return doorButtons;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -19,41 +19,45 @@ namespace Barotrauma
|
||||
get { return aiController; }
|
||||
}
|
||||
|
||||
public AICharacter(string file) : this(file, Vector2.Zero, null)
|
||||
{
|
||||
}
|
||||
//public AICharacter(string file) : this(file, Vector2.Zero, null)
|
||||
//{
|
||||
//}
|
||||
|
||||
public AICharacter(string file, Vector2 position)
|
||||
: this(file, position, null)
|
||||
{
|
||||
}
|
||||
//public AICharacter(string file, Vector2 position)
|
||||
// : this(file, position, null)
|
||||
//{
|
||||
//}
|
||||
|
||||
public AICharacter(CharacterInfo characterInfo, WayPoint spawnPoint, bool isNetworkPlayer = false)
|
||||
: this(characterInfo.File, spawnPoint.SimPosition, characterInfo, isNetworkPlayer)
|
||||
{
|
||||
//public AICharacter(CharacterInfo characterInfo, WayPoint spawnPoint, bool isNetworkPlayer = false)
|
||||
// : this(characterInfo.File, spawnPoint.SimPosition, characterInfo, isNetworkPlayer)
|
||||
//{
|
||||
|
||||
}
|
||||
//}
|
||||
|
||||
public AICharacter(CharacterInfo characterInfo, Vector2 position, bool isNetworkPlayer = false)
|
||||
: this(characterInfo.File, position, characterInfo, isNetworkPlayer)
|
||||
{
|
||||
}
|
||||
//public AICharacter(CharacterInfo characterInfo, Vector2 position, bool isNetworkPlayer = false)
|
||||
// : this(characterInfo.File, position, characterInfo, isNetworkPlayer)
|
||||
//{
|
||||
//}
|
||||
|
||||
public AICharacter(string file, Vector2 position, CharacterInfo characterInfo = null, bool isNetworkPlayer = false)
|
||||
: base(file, position, characterInfo, isNetworkPlayer)
|
||||
{
|
||||
aiController = new EnemyAIController(this, file);
|
||||
|
||||
|
||||
if (GameMain.Client != null && GameMain.Server == null) Enabled = false;
|
||||
}
|
||||
|
||||
public void SetAI(AIController aiController)
|
||||
{
|
||||
this.aiController = aiController;
|
||||
}
|
||||
|
||||
public override void Update(Camera cam, float deltaTime)
|
||||
{
|
||||
base.Update(cam, deltaTime);
|
||||
|
||||
if (isDead) return;
|
||||
|
||||
if (Controlled == this) return;
|
||||
|
||||
if (soundTimer > 0)
|
||||
{
|
||||
soundTimer -= deltaTime;
|
||||
|
||||
@@ -257,12 +257,12 @@ namespace Barotrauma
|
||||
|
||||
public override Vector2 SimPosition
|
||||
{
|
||||
get { return AnimController.Limbs[0].SimPosition; }
|
||||
get { return AnimController.RefLimb.SimPosition; }
|
||||
}
|
||||
|
||||
public Vector2 Position
|
||||
{
|
||||
get { return ConvertUnits.ToDisplayUnits(AnimController.Limbs[0].SimPosition); }
|
||||
get { return ConvertUnits.ToDisplayUnits(AnimController.RefLimb.SimPosition); }
|
||||
}
|
||||
|
||||
static Character()
|
||||
@@ -274,28 +274,53 @@ namespace Barotrauma
|
||||
DeathMsg[(int)CauseOfDeath.Pressure] = "been crushed by water pressure";
|
||||
DeathMsg[(int)CauseOfDeath.Burn] = "burnt to death";
|
||||
}
|
||||
|
||||
public Character(string file) : this(file, Vector2.Zero, null)
|
||||
|
||||
public static Character Create(string file, Vector2 position)
|
||||
{
|
||||
return Create(file, position, null);
|
||||
}
|
||||
|
||||
public Character(string file, Vector2 position)
|
||||
: this(file, position, null)
|
||||
public static Character Create(CharacterInfo characterInfo, WayPoint spawnPoint, bool isNetworkPlayer = false)
|
||||
{
|
||||
return Create(characterInfo.File, spawnPoint.SimPosition, characterInfo, isNetworkPlayer);
|
||||
}
|
||||
|
||||
public Character(CharacterInfo characterInfo, WayPoint spawnPoint, bool isNetworkPlayer = false)
|
||||
: this(characterInfo.File, spawnPoint.SimPosition, characterInfo, isNetworkPlayer)
|
||||
{
|
||||
|
||||
public static Character Create(CharacterInfo characterInfo, Vector2 position, bool isNetworkPlayer = false)
|
||||
{
|
||||
return Create(characterInfo.File, position, characterInfo, isNetworkPlayer);
|
||||
}
|
||||
|
||||
public Character(CharacterInfo characterInfo, Vector2 position, bool isNetworkPlayer = false)
|
||||
: this(characterInfo.File, position, characterInfo, isNetworkPlayer)
|
||||
public static Character Create(string file, Vector2 position, CharacterInfo characterInfo = null, bool isNetworkPlayer = false)
|
||||
{
|
||||
if (file != humanConfigFile)
|
||||
{
|
||||
var enemyCharacter = new AICharacter(file, position, characterInfo, isNetworkPlayer);
|
||||
var ai = new EnemyAIController(enemyCharacter, file);
|
||||
enemyCharacter.SetAI(ai);
|
||||
|
||||
return enemyCharacter;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (isNetworkPlayer)
|
||||
{
|
||||
var netCharacter = new Character(file, position, characterInfo, isNetworkPlayer);
|
||||
|
||||
return netCharacter;
|
||||
}
|
||||
else
|
||||
{
|
||||
var character = new AICharacter(file, position, characterInfo, isNetworkPlayer);
|
||||
var ai = new HumanAIController(character);
|
||||
character.SetAI(ai);
|
||||
|
||||
return character;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Character(string file, Vector2 position, CharacterInfo characterInfo = null, bool isNetworkPlayer = false)
|
||||
protected Character(string file, Vector2 position, CharacterInfo characterInfo = null, bool isNetworkPlayer = false)
|
||||
{
|
||||
|
||||
keys = new Key[Enum.GetNames(typeof(InputType)).Length];
|
||||
@@ -686,6 +711,8 @@ namespace Barotrauma
|
||||
/// </summary>
|
||||
public void ControlLocalPlayer(float deltaTime, Camera cam, bool moveCam = true)
|
||||
{
|
||||
AnimController.IsStanding = true;
|
||||
|
||||
Limb head = AnimController.GetLimb(LimbType.Head);
|
||||
|
||||
Lights.LightManager.ViewPos = ConvertUnits.ToDisplayUnits(head.SimPosition);
|
||||
@@ -873,7 +900,7 @@ namespace Barotrauma
|
||||
ControlLocalPlayer(deltaTime, cam);
|
||||
}
|
||||
|
||||
if (!(this is AICharacter)) Control(deltaTime, cam);
|
||||
if (controlled==this || !(this is AICharacter)) Control(deltaTime, cam);
|
||||
|
||||
UpdateSightRange();
|
||||
if (aiTarget != null) aiTarget.SoundRange = 0.0f;
|
||||
|
||||
@@ -314,17 +314,21 @@ namespace Barotrauma
|
||||
|
||||
if (targetMovement.Y >= 0.0f && lowestLimb.SimPosition.Y > ConvertUnits.ToSimUnits(structure.Rect.Y - Submarine.GridSize.Y * 8.0f))
|
||||
{
|
||||
stairs = null;
|
||||
return false;
|
||||
//stairs = null;
|
||||
//return false;
|
||||
}
|
||||
|
||||
Limb limb = f1.Body.UserData as Limb;
|
||||
if (limb != null && (limb.type == LimbType.LeftFoot || limb.type == LimbType.RightFoot))
|
||||
if (limb != null)// && (limb.type == LimbType.LeftFoot || limb.type == LimbType.RightFoot))
|
||||
{
|
||||
if (contact.Manifold.LocalNormal.Y >= 0.0f)
|
||||
{
|
||||
stairs = structure;
|
||||
return true;
|
||||
if (limb.SimPosition.Y < lowestLimb.SimPosition.Y+0.2f)
|
||||
{
|
||||
stairs = structure;
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -332,10 +336,6 @@ namespace Barotrauma
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -356,12 +356,15 @@ namespace Barotrauma
|
||||
avgVelocity = avgVelocity / Limbs.Count();
|
||||
|
||||
float impact = Vector2.Dot((f1.Body.LinearVelocity + avgVelocity) / 2.0f, -normal);
|
||||
|
||||
|
||||
if (GameMain.Server != null) impact = impact / 2.0f;
|
||||
|
||||
Limb l = (Limb)f1.Body.UserData;
|
||||
|
||||
if (impact > 1.0f && l.HitSound != null && l.soundTimer <= 0.0f) l.HitSound.Play(Math.Min(impact / 5.0f, 1.0f), impact * 100.0f, l.body.FarseerBody);
|
||||
float volume = stairs == null ? impact/5.0f : impact;
|
||||
volume= Math.Min(impact, 1.0f);
|
||||
|
||||
if (impact > 0.8f && l.HitSound != null && l.soundTimer <= 0.0f) l.HitSound.Play(volume, impact * 100.0f, l.body.FarseerBody);
|
||||
|
||||
if (impact > l.impactTolerance)
|
||||
{
|
||||
|
||||
@@ -223,7 +223,7 @@ namespace Barotrauma
|
||||
if (commands[1].ToLower()=="human")
|
||||
{
|
||||
WayPoint spawnPoint = WayPoint.GetRandom(SpawnType.Human);
|
||||
Character.Controlled = new Character(Character.HumanConfigFile, (spawnPoint == null) ? Vector2.Zero : spawnPoint.SimPosition);
|
||||
Character.Controlled = Character.Create(Character.HumanConfigFile, (spawnPoint == null) ? Vector2.Zero : spawnPoint.SimPosition);
|
||||
if (GameMain.GameSession != null)
|
||||
{
|
||||
SinglePlayerMode mode = GameMain.GameSession.gameMode as SinglePlayerMode;
|
||||
@@ -235,7 +235,7 @@ namespace Barotrauma
|
||||
else
|
||||
{
|
||||
WayPoint spawnPoint = WayPoint.GetRandom(SpawnType.Enemy);
|
||||
new AICharacter("Content/Characters/" + commands[1] + "/" + commands[1] + ".xml", (spawnPoint == null) ? Vector2.Zero : spawnPoint.SimPosition);
|
||||
Character.Create("Content/Characters/" + commands[1] + "/" + commands[1] + ".xml", (spawnPoint == null) ? Vector2.Zero : spawnPoint.SimPosition);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
@@ -45,7 +45,7 @@ namespace Barotrauma
|
||||
|
||||
position.X += Rand.Range(-0.5f, 0.5f);
|
||||
position.Y += Rand.Range(-0.5f, 0.5f);
|
||||
monsters[i] = new AICharacter(characterFile, position);
|
||||
monsters[i] = Character.Create(characterFile, position);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ namespace Barotrauma
|
||||
{
|
||||
Vector2 position = level.PositionsOfInterest[Rand.Int(level.PositionsOfInterest.Count, false)];
|
||||
|
||||
monster = new AICharacter(monsterFile, ConvertUnits.ToSimUnits(position+level.Position));
|
||||
monster = Character.Create(monsterFile, ConvertUnits.ToSimUnits(position+level.Position));
|
||||
}
|
||||
|
||||
public override void Update(float deltaTime)
|
||||
|
||||
@@ -199,7 +199,7 @@ namespace Barotrauma
|
||||
//WayPoint randomWayPoint = WayPoint.GetRandom(SpawnType.Human);
|
||||
//Vector2 position = (randomWayPoint == null) ? Vector2.Zero : randomWayPoint.SimPosition;
|
||||
|
||||
Character character = new Character(characterInfos[i], waypoints[i]);
|
||||
Character character = Character.Create(characterInfos[i], waypoints[i]);
|
||||
Character.Controlled = character;
|
||||
|
||||
if (!character.Info.StartItemsGiven)
|
||||
|
||||
@@ -47,7 +47,7 @@ namespace Barotrauma
|
||||
|
||||
CharacterInfo charInfo = new CharacterInfo(Character.HumanConfigFile, "", Gender.None, JobPrefab.List.Find(jp => jp.Name=="Engineer"));
|
||||
|
||||
Character character = new Character(charInfo, wayPoint.SimPosition);
|
||||
Character character = Character.Create(charInfo, wayPoint.SimPosition);
|
||||
Character.Controlled = character;
|
||||
character.GiveJobItems(null);
|
||||
|
||||
@@ -331,7 +331,7 @@ namespace Barotrauma
|
||||
}
|
||||
yield return new WaitForSeconds(1.0f);
|
||||
|
||||
var moloch = new AICharacter("Content/Characters/Moloch/moloch.xml", steering.Item.SimPosition + Vector2.UnitX * 25.0f);
|
||||
var moloch = Character.Create("Content/Characters/Moloch/moloch.xml", steering.Item.SimPosition + Vector2.UnitX * 25.0f);
|
||||
moloch.PlaySound(AIController.AiState.Attack);
|
||||
|
||||
yield return new WaitForSeconds(1.0f);
|
||||
|
||||
@@ -42,6 +42,7 @@ namespace Barotrauma.Items.Components
|
||||
foreach (MapEntity e in item.linkedTo)
|
||||
{
|
||||
linkedGap = e as Gap;
|
||||
linkedGap.ConnectedDoor = this;
|
||||
if (linkedGap != null) return linkedGap;
|
||||
}
|
||||
linkedGap = new Gap(item.Rect);
|
||||
|
||||
@@ -65,7 +65,7 @@ namespace Barotrauma.Items.Components
|
||||
var connectionPanel = item.GetComponent<ConnectionPanel>();
|
||||
if (connectionPanel!=null)
|
||||
{
|
||||
foreach (Connection c in connectionPanel.connections)
|
||||
foreach (Connection c in connectionPanel.Connections)
|
||||
{
|
||||
foreach (Wire w in c.Wires)
|
||||
{
|
||||
|
||||
@@ -210,7 +210,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
float rightWireX = x+width / 2 + wireInterval;
|
||||
float leftWireX = x + width / 2 - wireInterval;
|
||||
foreach (Connection c in panel.connections)
|
||||
foreach (Connection c in panel.Connections)
|
||||
{
|
||||
//if dragging a wire, let the Inventory know so that the wire can be
|
||||
//dropped or dragged from the panel to the players inventory
|
||||
@@ -250,7 +250,7 @@ namespace Barotrauma.Items.Components
|
||||
//and the wire hasn't been connected yet, draw it on the panel
|
||||
if (equippedWire!=null)
|
||||
{
|
||||
if (panel.connections.Find(c => c.Wires.Contains(equippedWire)) == null)
|
||||
if (panel.Connections.Find(c => c.Wires.Contains(equippedWire)) == null)
|
||||
{
|
||||
DrawWire(spriteBatch, equippedWire.Item, equippedWire.Item,
|
||||
new Vector2(x + width / 2, y + height - 100),
|
||||
|
||||
@@ -8,24 +8,24 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
class ConnectionPanel : ItemComponent
|
||||
{
|
||||
public List<Connection> connections;
|
||||
public List<Connection> Connections;
|
||||
|
||||
Character user;
|
||||
|
||||
public ConnectionPanel(Item item, XElement element)
|
||||
: base(item, element)
|
||||
{
|
||||
connections = new List<Connection>();
|
||||
Connections = new List<Connection>();
|
||||
|
||||
foreach (XElement subElement in element.Elements())
|
||||
{
|
||||
switch (subElement.Name.ToString())
|
||||
{
|
||||
case "input":
|
||||
connections.Add(new Connection(subElement, item));
|
||||
Connections.Add(new Connection(subElement, item));
|
||||
break;
|
||||
case "output":
|
||||
connections.Add(new Connection(subElement, item));
|
||||
Connections.Add(new Connection(subElement, item));
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -48,7 +48,7 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
XElement componentElement = base.Save(parentElement);
|
||||
|
||||
foreach (Connection c in connections)
|
||||
foreach (Connection c in Connections)
|
||||
{
|
||||
c.Save(componentElement);
|
||||
}
|
||||
@@ -58,7 +58,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
public override void OnMapLoaded()
|
||||
{
|
||||
foreach (Connection c in connections)
|
||||
foreach (Connection c in Connections)
|
||||
{
|
||||
c.ConnectLinked();
|
||||
}
|
||||
@@ -113,9 +113,9 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i<loadedConnections.Count && i<connections.Count; i++)
|
||||
for (int i = 0; i<loadedConnections.Count && i<Connections.Count; i++)
|
||||
{
|
||||
loadedConnections[i].wireId.CopyTo(connections[i].wireId, 0);
|
||||
loadedConnections[i].wireId.CopyTo(Connections[i].wireId, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -126,7 +126,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
public override bool FillNetworkData(Networking.NetworkEventType type, Lidgren.Network.NetBuffer message)
|
||||
{
|
||||
foreach (Connection c in connections)
|
||||
foreach (Connection c in Connections)
|
||||
{
|
||||
Wire[] wires = Array.FindAll(c.Wires, w => w != null);
|
||||
message.Write((byte)wires.Length);
|
||||
@@ -142,7 +142,7 @@ namespace Barotrauma.Items.Components
|
||||
public override void ReadNetworkData(Networking.NetworkEventType type, Lidgren.Network.NetBuffer message, float sendingTime)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine("connectionpanel update");
|
||||
foreach (Connection c in connections)
|
||||
foreach (Connection c in Connections)
|
||||
{
|
||||
//int wireCount = c.Wires.Length;
|
||||
c.ClearConnections();
|
||||
|
||||
@@ -210,7 +210,7 @@ namespace Barotrauma
|
||||
{
|
||||
ConnectionPanel panel = GetComponent<ConnectionPanel>();
|
||||
if (panel == null) return null;
|
||||
return panel.connections;
|
||||
return panel.Connections;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -790,7 +790,7 @@ namespace Barotrauma
|
||||
{
|
||||
ConnectionPanel panel = GetComponent<ConnectionPanel>();
|
||||
if (panel == null) return;
|
||||
foreach (Connection c in panel.connections)
|
||||
foreach (Connection c in panel.Connections)
|
||||
{
|
||||
if (c.Name != connectionName) continue;
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ using FarseerPhysics;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using System.Collections.ObjectModel;
|
||||
using Barotrauma.Items.Components;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
@@ -37,6 +38,8 @@ namespace Barotrauma
|
||||
set { open = MathHelper.Clamp(value, 0.0f, 1.0f); }
|
||||
}
|
||||
|
||||
public Door ConnectedDoor;
|
||||
|
||||
public Vector2 FlowForce
|
||||
{
|
||||
get { return flowForce*soundVolume; }
|
||||
@@ -133,43 +136,6 @@ namespace Barotrauma
|
||||
linkedTo.Add(hulls[0]);
|
||||
if (hulls[1] != null) linkedTo.Add(hulls[1]);
|
||||
|
||||
//if (hull1 != null && hull2 != null)
|
||||
//{
|
||||
// if (isHorizontal)
|
||||
// {
|
||||
// //make sure that water1 is the lefthand room
|
||||
// //or that water2 is null if the gap doesn't lead to another room
|
||||
// if (hull1.Rect.X < hull2.Rect.X)
|
||||
// {
|
||||
// linkedTo.Add(hull1);
|
||||
// linkedTo.Add(hull2);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// linkedTo.Add(hull2);
|
||||
// linkedTo.Add(hull1);
|
||||
// }
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// //make sure that water1 is the room on the top
|
||||
// //or that water2 is null if the gap doesn't lead to another room
|
||||
// if (hull1.Rect.Y > hull2.Rect.Y)
|
||||
// {
|
||||
// linkedTo.Add(hull1);
|
||||
// linkedTo.Add(hull2);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// linkedTo.Add(hull2);
|
||||
// linkedTo.Add(hull1);
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
// linkedTo.Add(hull1);
|
||||
//}
|
||||
}
|
||||
|
||||
public override void Draw(SpriteBatch sb, bool editing, bool back = true)
|
||||
|
||||
@@ -39,6 +39,7 @@ namespace Barotrauma
|
||||
public static MapEntityPrefab Selected
|
||||
{
|
||||
get { return selected; }
|
||||
set { selected = value; }
|
||||
}
|
||||
|
||||
public virtual bool IsLinkable
|
||||
|
||||
@@ -10,7 +10,7 @@ using System.Collections.ObjectModel;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
public enum SpawnType { None, Human, Enemy, Cargo };
|
||||
public enum SpawnType { None, Human, Enemy, Cargo, Path };
|
||||
class WayPoint : MapEntity
|
||||
{
|
||||
public static List<WayPoint> WayPointList = new List<WayPoint>();
|
||||
@@ -23,6 +23,12 @@ namespace Barotrauma
|
||||
//only characters with this job will be spawned at the waypoint
|
||||
private JobPrefab assignedJob;
|
||||
|
||||
public Gap ConnectedGap
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public SpawnType SpawnType
|
||||
{
|
||||
get { return spawnType; }
|
||||
@@ -60,6 +66,13 @@ namespace Barotrauma
|
||||
WayPointList.Add(this);
|
||||
}
|
||||
|
||||
public WayPoint(Vector2 position, SpawnType spawnType, Gap gap = null)
|
||||
:this(new Rectangle((int)position.X-3, (int)position.Y+3, 6, 6))
|
||||
{
|
||||
this.spawnType = spawnType;
|
||||
ConnectedGap = gap;
|
||||
}
|
||||
|
||||
|
||||
public override void Draw(SpriteBatch spriteBatch, bool editing, bool back=true)
|
||||
{
|
||||
@@ -70,6 +83,9 @@ namespace Barotrauma
|
||||
Color clr = (isSelected) ? Color.Red : Color.LightGreen;
|
||||
GUI.DrawRectangle(spriteBatch, new Rectangle(pos.X - rect.Width / 2, -pos.Y - rect.Height / 2, rect.Width, rect.Height), clr, true);
|
||||
|
||||
|
||||
spriteBatch.DrawString(GUI.SmallFont, Position.ToString(), new Vector2(Position.X, -Position.Y), Color.White);
|
||||
|
||||
foreach (MapEntity e in linkedTo)
|
||||
{
|
||||
GUI.DrawLine(spriteBatch,
|
||||
@@ -194,6 +210,120 @@ namespace Barotrauma
|
||||
return editingHUD;
|
||||
}
|
||||
|
||||
public static void GenerateSubWaypoints()
|
||||
{
|
||||
float minDist = 200.0f;
|
||||
float heightFromFloor = 100.0f;
|
||||
|
||||
foreach (Hull hull in Hull.hullList)
|
||||
{
|
||||
WayPoint prevWaypoint = null;
|
||||
|
||||
if (hull.Rect.Width<minDist*3.0f)
|
||||
{
|
||||
var wayPoint = new WayPoint(
|
||||
new Vector2(hull.Rect.X + hull.Rect.Width / 2.0f, hull.Rect.Y - hull.Rect.Height + heightFromFloor), SpawnType.Path);
|
||||
continue;
|
||||
}
|
||||
|
||||
for (float x = hull.Rect.X + minDist; x <= hull.Rect.X + hull.Rect.Width - minDist; x += minDist)
|
||||
{
|
||||
var wayPoint = new WayPoint(new Vector2(x, hull.Rect.Y - hull.Rect.Height + heightFromFloor), SpawnType.Path);
|
||||
|
||||
if (prevWaypoint != null) wayPoint.ConnectTo(prevWaypoint);
|
||||
|
||||
prevWaypoint = wayPoint;
|
||||
}
|
||||
}
|
||||
|
||||
List<Structure> stairList = new List<Structure>();
|
||||
foreach (MapEntity me in MapEntity.mapEntityList)
|
||||
{
|
||||
Structure stairs = me as Structure;
|
||||
if (stairs == null) continue;
|
||||
|
||||
if (stairs.StairDirection != Direction.None) stairList.Add(stairs);
|
||||
}
|
||||
|
||||
foreach (Structure stairs in stairList)
|
||||
{
|
||||
WayPoint[] stairPoints = new WayPoint[2];
|
||||
|
||||
stairPoints[0] = new WayPoint(
|
||||
new Vector2(stairs.Rect.X - 50.0f,
|
||||
stairs.Rect.Y - (stairs.StairDirection == Direction.Left ? 80 : stairs.Rect.Height) + heightFromFloor), SpawnType.Path);
|
||||
|
||||
stairPoints[1] = new WayPoint(
|
||||
new Vector2(stairs.Rect.Right + 50.0f,
|
||||
stairs.Rect.Y - (stairs.StairDirection == Direction.Left ? stairs.Rect.Height : 80) + heightFromFloor), SpawnType.Path);
|
||||
|
||||
for (int i = 0; i < 2; i++ )
|
||||
{
|
||||
for (int dir = -1; dir <= 1; dir += 2)
|
||||
{
|
||||
WayPoint closest = stairPoints[i].FindClosest(dir, true, 30.0f);
|
||||
if (closest == null) continue;
|
||||
stairPoints[i].ConnectTo(closest);
|
||||
}
|
||||
}
|
||||
|
||||
stairPoints[0].ConnectTo(stairPoints[1]);
|
||||
}
|
||||
|
||||
foreach (Gap gap in Gap.GapList)
|
||||
{
|
||||
if (!gap.isHorizontal) continue;
|
||||
|
||||
var wayPoint = new WayPoint(
|
||||
new Vector2(gap.Rect.Center.X, gap.Rect.Y - gap.Rect.Height + heightFromFloor), SpawnType.Path, gap);
|
||||
|
||||
for (int dir = -1; dir <= 1; dir += 2)
|
||||
{
|
||||
WayPoint closest = wayPoint.FindClosest(dir, true, 30.0f);
|
||||
if (closest == null) continue;
|
||||
wayPoint.ConnectTo(closest);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private WayPoint FindClosest(int dir, bool horizontalSearch, float tolerance)
|
||||
{
|
||||
if (dir != -1 && dir != 1) return null;
|
||||
|
||||
float closestDist = 0.0f;
|
||||
WayPoint closest = null;
|
||||
|
||||
if (horizontalSearch)
|
||||
{
|
||||
foreach (WayPoint wp in WayPointList)
|
||||
{
|
||||
if (wp.SpawnType != SpawnType.Path || wp == this) continue;
|
||||
|
||||
if (Math.Abs(wp.Position.Y - Position.Y) > tolerance) continue;
|
||||
|
||||
float diff = wp.Position.X - Position.X;
|
||||
if (Math.Sign(diff) != dir) continue;
|
||||
|
||||
diff = Math.Abs(diff);
|
||||
if (closest == null || diff < closestDist)
|
||||
{
|
||||
if (Submarine.CheckVisibility(SimPosition, wp.SimPosition) != null) continue;
|
||||
|
||||
closestDist = diff;
|
||||
closest = wp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return closest;
|
||||
}
|
||||
|
||||
private void ConnectTo(WayPoint wayPoint2)
|
||||
{
|
||||
linkedTo.Add(wayPoint2);
|
||||
wayPoint2.linkedTo.Add(this);
|
||||
}
|
||||
|
||||
public static WayPoint GetRandom(SpawnType spawnType = SpawnType.None, Job assignedJob = null)
|
||||
{
|
||||
List<WayPoint> wayPoints = new List<WayPoint>();
|
||||
|
||||
@@ -751,8 +751,8 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
|
||||
Character character = (closestWaypoint == null) ?
|
||||
new Character(ch, position, !isMyCharacter) :
|
||||
new Character(ch, closestWaypoint, !isMyCharacter);
|
||||
Character.Create(ch, position, !isMyCharacter) :
|
||||
Character.Create(ch, closestWaypoint, !isMyCharacter);
|
||||
|
||||
character.ID = ID;
|
||||
|
||||
|
||||
@@ -756,14 +756,14 @@ namespace Barotrauma.Networking
|
||||
|
||||
for (int i = 0; i < ConnectedClients.Count; i++)
|
||||
{
|
||||
ConnectedClients[i].Character = new Character(
|
||||
ConnectedClients[i].Character = Character.Create(
|
||||
ConnectedClients[i].characterInfo, assignedWayPoints[i], true);
|
||||
ConnectedClients[i].Character.GiveJobItems(assignedWayPoints[i]);
|
||||
}
|
||||
|
||||
if (characterInfo != null)
|
||||
{
|
||||
myCharacter = new Character(characterInfo, assignedWayPoints[assignedWayPoints.Length - 1]);
|
||||
myCharacter = Character.Create(characterInfo, assignedWayPoints[assignedWayPoints.Length - 1]);
|
||||
Character.Controlled = myCharacter;
|
||||
|
||||
myCharacter.GiveJobItems(assignedWayPoints[assignedWayPoints.Length - 1]);
|
||||
|
||||
@@ -278,7 +278,7 @@ namespace Barotrauma
|
||||
return GameMain.Config.KeyBind(inputType).IsHit();
|
||||
}
|
||||
|
||||
public static bool KeyDOwn(InputType inputType)
|
||||
public static bool KeyDown(InputType inputType)
|
||||
{
|
||||
return GameMain.Config.KeyBind(inputType).IsDown();
|
||||
}
|
||||
|
||||
@@ -81,6 +81,9 @@ namespace Barotrauma
|
||||
button = new GUIButton(new Rectangle(0, 220, 0, 20), "Character mode", Alignment.Left, GUI.Style, GUIpanel);
|
||||
button.ToolTip = "Allows you to pick up and use items. Useful for things such as placing items inside closets, turning devices on/off and doing the wiring.";
|
||||
button.OnClicked = ToggleCharacterMode;
|
||||
|
||||
button = new GUIButton(new Rectangle(0, 270, 0, 20), "Generate waypoints", Alignment.Left, GUI.Style, GUIpanel);
|
||||
button.OnClicked = GenerateWaypoints;
|
||||
|
||||
GUItabs = new GUIComponent[2];
|
||||
int width = 400, height = 400;
|
||||
@@ -140,6 +143,8 @@ namespace Barotrauma
|
||||
|
||||
GUIComponent.MouseOn = null;
|
||||
|
||||
MapEntityPrefab.Selected = null;
|
||||
|
||||
if (dummyCharacter != null)
|
||||
{
|
||||
dummyCharacter.Remove();
|
||||
@@ -152,7 +157,7 @@ namespace Barotrauma
|
||||
{
|
||||
if (dummyCharacter != null) dummyCharacter.Remove();
|
||||
|
||||
dummyCharacter = new Character(Character.HumanConfigFile, Vector2.Zero);
|
||||
dummyCharacter = Character.Create(Character.HumanConfigFile, Vector2.Zero);
|
||||
Character.Controlled = dummyCharacter;
|
||||
GameMain.World.ProcessChanges();
|
||||
}
|
||||
@@ -204,6 +209,12 @@ namespace Barotrauma
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool GenerateWaypoints(GUIButton button, object obj)
|
||||
{
|
||||
WayPoint.GenerateSubWaypoints();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Allows the game to run logic such as updating the world,
|
||||
@@ -324,10 +335,6 @@ namespace Barotrauma
|
||||
|
||||
}
|
||||
|
||||
//if (PlayerInput.GetMouseState.LeftButton != ButtonState.Pressed)
|
||||
//{
|
||||
// Inventory.draggingItem = null;
|
||||
//}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -336,10 +343,9 @@ namespace Barotrauma
|
||||
|
||||
GUI.Draw((float)deltaTime, spriteBatch, cam);
|
||||
|
||||
if (!PlayerInput.LeftButtonDown()) Inventory.draggingItem = null;
|
||||
if (!PlayerInput.LeftButtonDown()) Inventory.draggingItem = null;
|
||||
|
||||
spriteBatch.End();
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Binary file not shown.
Reference in New Issue
Block a user