diff --git a/Subsurface/Barotrauma.csproj b/Subsurface/Barotrauma.csproj index f75ce7183..4d256f821 100644 --- a/Subsurface/Barotrauma.csproj +++ b/Subsurface/Barotrauma.csproj @@ -62,7 +62,10 @@ + + + diff --git a/Subsurface/Source/Characters/AI/AITarget.cs b/Subsurface/Source/Characters/AI/AITarget.cs index 46e006afa..b4f0f3af6 100644 --- a/Subsurface/Source/Characters/AI/AITarget.cs +++ b/Subsurface/Source/Characters/AI/AITarget.cs @@ -27,7 +27,7 @@ namespace Barotrauma set { sightRange = value; } } - public Vector2 Position + public Vector2 SimPosition { get { return Entity.SimPosition; } } diff --git a/Subsurface/Source/Characters/AI/EnemyAIController.cs b/Subsurface/Source/Characters/AI/EnemyAIController.cs index 8e57c410e..e777daa91 100644 --- a/Subsurface/Source/Characters/AI/EnemyAIController.cs +++ b/Subsurface/Source/Characters/AI/EnemyAIController.cs @@ -21,10 +21,7 @@ namespace Barotrauma //0.0 = doesn't attack targets of the type //positive values = attacks targets of this type //negative values = escapes targets of this type - private float attackRooms; - private float attackHumans; - private float attackWeaker; - private float attackStronger; + private float attackRooms, attackHumans, attackWeaker, attackStronger; private float updateTargetsTimer; @@ -165,7 +162,7 @@ namespace Barotrauma selectedTargetMemory.Priority -= deltaTime; - Vector2 attackPosition = selectedAiTarget.Position; + Vector2 attackPosition = selectedAiTarget.SimPosition; if (wallAttackPos != Vector2.Zero) attackPosition = wallAttackPos; if (coolDownTimer>0.0f) @@ -230,7 +227,7 @@ namespace Barotrauma targetEntity = null; //check if there's a wall between the target and the Character Vector2 rayStart = Character.AnimController.Limbs[0].SimPosition; - Vector2 rayEnd = selectedAiTarget.Position; + Vector2 rayEnd = selectedAiTarget.SimPosition; Body closestBody = Submarine.CheckVisibility(rayStart, rayEnd); if (Submarine.LastPickedFraction == 1.0f || closestBody == null) @@ -391,7 +388,7 @@ namespace Barotrauma dist = Vector2.Distance( character.AnimController.Limbs[0].SimPosition, - target.Position); + target.SimPosition); dist = ConvertUnits.ToDisplayUnits(dist); AITargetMemory targetMemory = FindTargetMemory(target); @@ -402,7 +399,7 @@ namespace Barotrauma if (Math.Abs(valueModifier) > Math.Abs(targetValue) && (dist < target.SightRange * sight || dist < target.SoundRange * hearing)) { Vector2 rayStart = character.AnimController.Limbs[0].SimPosition; - Vector2 rayEnd = target.Position; + Vector2 rayEnd = target.SimPosition; Body closestBody = Submarine.CheckVisibility(rayStart, rayEnd); Structure closestStructure = (closestBody == null) ? null : closestBody.UserData as Structure; @@ -493,7 +490,7 @@ namespace Barotrauma if (selectedAiTarget!=null) { - GUI.DrawLine(spriteBatch, pos, ConvertUnits.ToDisplayUnits(new Vector2(selectedAiTarget.Position.X, -selectedAiTarget.Position.Y)), Color.Red); + GUI.DrawLine(spriteBatch, pos, ConvertUnits.ToDisplayUnits(new Vector2(selectedAiTarget.SimPosition.X, -selectedAiTarget.SimPosition.Y)), Color.Red); if (wallAttackPos!=Vector2.Zero) { diff --git a/Subsurface/Source/Characters/AI/HumanAIController.cs b/Subsurface/Source/Characters/AI/HumanAIController.cs index e67a0d049..b092bd76c 100644 --- a/Subsurface/Source/Characters/AI/HumanAIController.cs +++ b/Subsurface/Source/Characters/AI/HumanAIController.cs @@ -13,20 +13,27 @@ namespace Barotrauma private AIObjectiveManager objectiveManager; + private IndoorsSteeringManager indoorsSteeringManager; + private SteeringManager outdoorsSteeringManager; + private AITarget selectedAiTarget; private float updateObjectiveTimer; public HumanAIController(Character c) : base(c) { - steeringManager = new PathSteeringManager(this); + indoorsSteeringManager = new IndoorsSteeringManager(this, true); + outdoorsSteeringManager = new SteeringManager(this); objectiveManager = new AIObjectiveManager(c); - objectiveManager.AddObjective(new AIObjectiveFindSafety()); + objectiveManager.AddObjective(new AIObjectiveFindSafety(c)); + objectiveManager.AddObjective(new AIObjectiveIdle(c)); } public override void Update(float deltaTime) { + steeringManager = Character.AnimController.CurrentHull == null ? outdoorsSteeringManager : indoorsSteeringManager; + if (updateObjectiveTimer>0.0f) { updateObjectiveTimer -= deltaTime; @@ -46,12 +53,15 @@ namespace Barotrauma Character.AnimController.IgnorePlatforms = (-Character.AnimController.TargetMovement.Y > Math.Abs(Character.AnimController.TargetMovement.X)); - if (Math.Abs(Character.AnimController.TargetMovement.X)>0.1f) + if (Math.Abs(Character.AnimController.TargetMovement.X) > 0.1f && !Character.AnimController.InWater) { Character.AnimController.TargetDir = Character.AnimController.TargetMovement.X > 0.0f ? Direction.Right : Direction.Left; } - steeringManager.Update(); + float currObjectivePriority = objectiveManager.CurrentObjective == null ? 0.0f : objectiveManager.CurrentObjective.GetPriority(Character); + float moveSpeed = MathHelper.Clamp(currObjectivePriority/10.0f, 1.0f, 3.0f); + + steeringManager.Update(moveSpeed); } public override void SelectTarget(AITarget target) @@ -61,13 +71,12 @@ namespace Barotrauma 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); + GUI.DrawLine(spriteBatch, new Vector2(Character.Position.X, -Character.Position.Y), ConvertUnits.ToDisplayUnits(new Vector2(selectedAiTarget.SimPosition.X, -selectedAiTarget.SimPosition.Y)), Color.Red); } - PathSteeringManager pathSteering = steeringManager as PathSteeringManager; + IndoorsSteeringManager pathSteering = steeringManager as IndoorsSteeringManager; if (pathSteering == null || pathSteering.CurrentPath == null || pathSteering.CurrentPath.CurrentNode==null) return; GUI.DrawLine(spriteBatch, @@ -83,7 +92,6 @@ namespace Barotrauma new Vector2(pathSteering.CurrentPath.Nodes[i - 1].Position.X, -pathSteering.CurrentPath.Nodes[i-1].Position.Y), Color.LightGreen); } - } } } diff --git a/Subsurface/Source/Characters/AI/Objectives/AIObjective.cs b/Subsurface/Source/Characters/AI/Objectives/AIObjective.cs index 420d1441c..5da96ddf8 100644 --- a/Subsurface/Source/Characters/AI/Objectives/AIObjective.cs +++ b/Subsurface/Source/Characters/AI/Objectives/AIObjective.cs @@ -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(); + + this.character = character; } /// @@ -26,20 +35,20 @@ namespace Barotrauma /// need to be completed before this one /// /// the character who's trying to achieve the objective - 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(); } } } diff --git a/Subsurface/Source/Characters/AI/Objectives/AIObjectiveFindSafety.cs b/Subsurface/Source/Characters/AI/Objectives/AIObjectiveFindSafety.cs index e79d065a3..2fec74906 100644 --- a/Subsurface/Source/Characters/AI/Objectives/AIObjectiveFindSafety.cs +++ b/Subsurface/Source/Characters/AI/Objectives/AIObjectiveFindSafety.cs @@ -12,16 +12,26 @@ namespace Barotrauma const float MinSafety = 50.0f; AIObjectiveGoTo gotoObjective; + + private List unreachable; float currenthullSafety; float searchHullTimer; - protected override void Act(float deltaTime, Character character) + public AIObjectiveFindSafety(Character character) + : base(character) + { + unreachable = new List(); + } + + 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; diff --git a/Subsurface/Source/Characters/AI/Objectives/AIObjectiveFixLeak.cs b/Subsurface/Source/Characters/AI/Objectives/AIObjectiveFixLeak.cs new file mode 100644 index 000000000..0d23d7de4 --- /dev/null +++ b/Subsurface/Source/Characters/AI/Objectives/AIObjectiveFixLeak.cs @@ -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)); + } + } + } + } +} diff --git a/Subsurface/Source/Characters/AI/Objectives/AIObjectiveGetItem.cs b/Subsurface/Source/Characters/AI/Objectives/AIObjectiveGetItem.cs new file mode 100644 index 000000000..f2e1dc6ba --- /dev/null +++ b/Subsurface/Source/Characters/AI/Objectives/AIObjectiveGetItem.cs @@ -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; + } + } +} diff --git a/Subsurface/Source/Characters/AI/Objectives/AIObjectiveGoTo.cs b/Subsurface/Source/Characters/AI/Objectives/AIObjectiveGoTo.cs index e8bd7d3ff..63e6a1614 100644 --- a/Subsurface/Source/Characters/AI/Objectives/AIObjectiveGoTo.cs +++ b/Subsurface/Source/Characters/AI/Objectives/AIObjectiveGoTo.cs @@ -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; } } } diff --git a/Subsurface/Source/Characters/AI/Objectives/AIObjectiveIdle.cs b/Subsurface/Source/Characters/AI/Objectives/AIObjectiveIdle.cs new file mode 100644 index 000000000..1d24d7f78 --- /dev/null +++ b/Subsurface/Source/Characters/AI/Objectives/AIObjectiveIdle.cs @@ -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 targetHulls = new List(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; + } + } +} diff --git a/Subsurface/Source/Characters/AI/Objectives/AIObjectiveManager.cs b/Subsurface/Source/Characters/AI/Objectives/AIObjectiveManager.cs index 68d4f82ea..3f413d27f 100644 --- a/Subsurface/Source/Characters/AI/Objectives/AIObjectiveManager.cs +++ b/Subsurface/Source/Characters/AI/Objectives/AIObjectiveManager.cs @@ -10,6 +10,14 @@ namespace Barotrauma private List 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); } } } diff --git a/Subsurface/Source/Characters/AI/Objectives/AIObjectiveOperateItem.cs b/Subsurface/Source/Characters/AI/Objectives/AIObjectiveOperateItem.cs index 8da97fd54..fe4107793 100644 --- a/Subsurface/Source/Characters/AI/Objectives/AIObjectiveOperateItem.cs +++ b/Subsurface/Source/Characters/AI/Objectives/AIObjectiveOperateItem.cs @@ -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 } diff --git a/Subsurface/Source/Characters/AI/PathFinder.cs b/Subsurface/Source/Characters/AI/PathFinder.cs index f6fe77c3a..5af610785 100644 --- a/Subsurface/Source/Characters/AI/PathFinder.cs +++ b/Subsurface/Source/Characters/AI/PathFinder.cs @@ -77,8 +77,8 @@ namespace Barotrauma class PathFinder { - public delegate float GetNodePenaltyHandler(PathNode node, PathNode prevNode); - public GetNodePenaltyHandler GetNodePriority; + public delegate float? GetNodePenaltyHandler(PathNode node, PathNode prevNode); + public GetNodePenaltyHandler GetNodePenalty; List nodes; @@ -95,12 +95,14 @@ namespace Barotrauma { System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch(); sw.Start(); - + float closestDist = 0.0f; PathNode startNode = null; foreach (PathNode node in nodes) { - float dist = Vector2.Distance(start,node.Position); + float dist = System.Math.Abs(start.X-node.Position.X)+ + System.Math.Abs(start.Y - node.Position.Y)*10.0f + + Vector2.Distance(end,node.Position)/2.0f; if (dist openableButtons; + private Character character; public SteeringPath CurrentPath { @@ -31,15 +31,15 @@ namespace Barotrauma private float findPathTimer; - public PathSteeringManager(ISteerable host) + public IndoorsSteeringManager(ISteerable host, bool canOpenDoors) : base(host) { pathFinder = new PathFinder(WayPoint.WayPointList.FindAll(wp => wp.SpawnType == SpawnType.Path), true); - pathFinder.GetNodePriority = GetNodePriority; + pathFinder.GetNodePenalty = GetNodePenalty; + + this.canOpenDoors = canOpenDoors; character = (host as AIController).Character; - - openableButtons = new List(); } public override void Update(float speed = 1) @@ -53,37 +53,22 @@ namespace Barotrauma protected override Vector2 DoSteeringSeek(Vector2 target, float speed = 1) { //find a new path if one hasn't been found yet or the target is different from the current target - if (currentPath == null || Vector2.DistanceSquared(target, currentTarget)>10.0f) + if (currentPath == null || Vector2.Distance(target, currentTarget)>1.0f || findPathTimer < -10.0f) { if (findPathTimer > 0.0f) return Vector2.Zero; currentTarget = target; - currentPath = pathFinder.FindPath(host.SimPosition, ConvertUnits.ToSimUnits(target)); - + currentPath = pathFinder.FindPath(host.SimPosition, 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; } @@ -91,61 +76,77 @@ namespace Barotrauma { if (currentPath == null) return Vector2.Zero; - currentPath.CheckProgress(host.SimPosition, 0.45f); + if (canOpenDoors) CheckDoorsInPath(); + + currentPath.CheckProgress(host.SimPosition, character.AnimController.InWater ? 1.0f : 0.6f); if (currentPath.CurrentNode == null) return Vector2.Zero; return currentPath.CurrentNode.SimPosition - host.SimPosition; } - private float GetNodePriority(PathNode node, PathNode nextNode) + private void CheckDoorsInPath() { - if (character==null) return 0.0f; - if (nextNode.Waypoint.ConnectedGap!=null) + for (int i = 0; i < 2; i++) + { + WayPoint node = i == 0 ? currentPath.CurrentNode : currentPath.PrevNode; + + if (node == null || node.ConnectedGap == null || node.ConnectedGap.ConnectedDoor == null) continue; + + var door = node.ConnectedGap.ConnectedDoor; + + bool open = currentPath.CurrentNode != null && + Math.Sign(door.Item.SimPosition.X - host.SimPosition.X) == Math.Sign(currentPath.CurrentNode.SimPosition.X - host.SimPosition.X); + + //toggle the door if it's the previous node and open, or if it's current node and closed + if (door.IsOpen != open) + { + var buttons = door.GetButtons(); + foreach (Controller controller in buttons) + { + if (Vector2.Distance(controller.Item.SimPosition, character.SimPosition) > controller.Item.PickDistance * 2.0f) continue; + + controller.Item.Pick(character, false, true); + break; + } + } + } + } + + private float? GetNodePenalty(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); + if (!canOpenDoors) return null; + + var doorButtons = nextNode.Waypoint.ConnectedGap.ConnectedDoor.GetButtons(); 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; + if (!button.HasRequiredItems(character, false)) return null; } } + if (node.Waypoint!=null && node.Waypoint.CurrentHull!=null) + { + var hull = node.Waypoint.CurrentHull; + + float penalty = hull.FireSources.Any() ? 1000.0f : 0.0f; + + if (character.NeedsAir && hull.Volume / hull.Rect.Width > 100.0f) penalty += 500.0f; + if (character.PressureProtection < 10.0f && hull.Volume > hull.FullVolume) penalty += 1000.0f; + } + return 0.0f; } - private List GetDoorButtons(Door door) - { - if (door == null) return new List(); - ConnectionPanel connectionPanel = door.Item.GetComponent(); - List doorButtons = new List(); - - 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(); - if (controller != null) - { - doorButtons.Add(controller); - if (!openableButtons.Contains(controller)) openableButtons.Add(controller); - } - } - } - - return doorButtons; - } } } diff --git a/Subsurface/Source/Characters/AI/SteeringPath.cs b/Subsurface/Source/Characters/AI/SteeringPath.cs index e52f748a7..d508da2d8 100644 --- a/Subsurface/Source/Characters/AI/SteeringPath.cs +++ b/Subsurface/Source/Characters/AI/SteeringPath.cs @@ -9,9 +9,16 @@ namespace Barotrauma int currentIndex; - public SteeringPath() + public bool Unreachable + { + get; + private set; + } + + public SteeringPath(bool unreachable = false) { nodes = new List(); + Unreachable = unreachable; } public void AddNode(WayPoint node) @@ -20,6 +27,20 @@ namespace Barotrauma nodes.Add(node); } + public int CurrentIndex + { + get { return currentIndex; } + } + + public WayPoint PrevNode + { + get + { + if (currentIndex-1 < 0 || currentIndex-1 > nodes.Count - 1) return null; + return nodes[currentIndex-1]; + } + } + public WayPoint CurrentNode { get diff --git a/Subsurface/Source/Characters/AICharacter.cs b/Subsurface/Source/Characters/AICharacter.cs index e4563302b..ba52cab67 100644 --- a/Subsurface/Source/Characters/AICharacter.cs +++ b/Subsurface/Source/Characters/AICharacter.cs @@ -75,7 +75,7 @@ namespace Barotrauma { base.DrawFront(spriteBatch); - if (GameMain.DebugDraw) aiController.DebugDraw(spriteBatch); + if (GameMain.DebugDraw && !isDead) aiController.DebugDraw(spriteBatch); } public override AttackResult AddDamage(IDamageable attacker, Vector2 position, Attack attack, float deltaTime, bool playSound = false) diff --git a/Subsurface/Source/Characters/Character.cs b/Subsurface/Source/Characters/Character.cs index 6c0a21867..f75d75bfe 100644 --- a/Subsurface/Source/Characters/Character.cs +++ b/Subsurface/Source/Characters/Character.cs @@ -84,6 +84,17 @@ namespace Barotrauma //the name of the species (e.q. human) public readonly string SpeciesName; + protected float soundTimer; + protected float soundInterval; + + private float bleeding; + + private Sound[] sounds; + private float[] soundRange; + //which AIstate each sound is for + private AIController.AiState[] soundStates; + + private CharacterInfo info; public CharacterInfo Info @@ -99,16 +110,6 @@ namespace Barotrauma } } - protected float soundTimer; - protected float soundInterval; - - private float bleeding; - - private Sound[] sounds; - private float[] soundRange; - //which AIstate each sound is for - private AIController.AiState[] soundStates; - public string Name { get @@ -171,6 +172,7 @@ namespace Barotrauma { get { return aiTarget.SightRange; } } + private float pressureProtection; public float PressureProtection { @@ -181,11 +183,17 @@ namespace Barotrauma } } + public bool NeedsAir + { + get { return needsAir; } + } + public float Oxygen { get { return oxygen; } set { + if (!MathUtils.IsValid(value)) return; oxygen = MathHelper.Clamp(value, 0.0f, 100.0f); if (oxygen == 0.0f) Kill(CauseOfDeath.Suffocation); } @@ -567,6 +575,8 @@ namespace Barotrauma AnimController.TargetMovement = targetMovement; AnimController.IsStanding = true; + AnimController.IgnorePlatforms = targetMovement.Y < 0.0f; + if (AnimController.onGround && !AnimController.InWater && AnimController.Anim != AnimController.Animation.UsingConstruction) @@ -877,7 +887,7 @@ namespace Barotrauma if (isDead) return; - if (!(this is AICharacter)) + if (!(AnimController is FishAnimController)) { bool protectedFromPressure = PressureProtection > 0.0f; @@ -993,7 +1003,7 @@ namespace Barotrauma AnimController.DebugDraw(spriteBatch); } - Vector2 healthBarPos = new Vector2(Position.X - 50, -Position.Y - 50.0f); + Vector2 healthBarPos = new Vector2(Position.X - 50, -Position.Y - 100.0f); GUI.DrawRectangle(spriteBatch, new Rectangle((int)healthBarPos.X - 2, (int)healthBarPos.Y - 2, 100 + 4, 15 + 4), Color.Black, false); GUI.DrawRectangle(spriteBatch, new Rectangle((int)healthBarPos.X, (int)healthBarPos.Y, (int)(100.0f * (health / maxHealth)), 15), Color.Red, true); } diff --git a/Subsurface/Source/Characters/CharacterInfo.cs b/Subsurface/Source/Characters/CharacterInfo.cs index 162931585..cc6b805d0 100644 --- a/Subsurface/Source/Characters/CharacterInfo.cs +++ b/Subsurface/Source/Characters/CharacterInfo.cs @@ -219,7 +219,7 @@ namespace Barotrauma public void UpdateCharacterItems() { pickedItems.Clear(); - foreach (Item item in Character.Inventory.items) + foreach (Item item in Character.Inventory.Items) { pickedItems.Add(item == null ? (ushort)0 : item.ID); } diff --git a/Subsurface/Source/Characters/HumanoidAnimController.cs b/Subsurface/Source/Characters/HumanoidAnimController.cs index 8244d80e6..3fea8f485 100644 --- a/Subsurface/Source/Characters/HumanoidAnimController.cs +++ b/Subsurface/Source/Characters/HumanoidAnimController.cs @@ -133,11 +133,7 @@ namespace Barotrauma stunTimer -= deltaTime; return; } - - IgnorePlatforms = (TargetMovement.Y < 0.0f); - - - + if (Anim != Animation.UsingConstruction) ResetPullJoints(); if (TargetDir != dir) Flip(); diff --git a/Subsurface/Source/DebugConsole.cs b/Subsurface/Source/DebugConsole.cs index b245b55df..8226cec06 100644 --- a/Subsurface/Source/DebugConsole.cs +++ b/Subsurface/Source/DebugConsole.cs @@ -269,6 +269,12 @@ namespace Barotrauma case "edit": GameMain.EditMapScreen.Select(); break; + case "test": + Submarine.Load("aegir mark ii"); + GameMain.DebugDraw = true; + GameMain.LightManager.LosEnabled = false; + GameMain.EditMapScreen.Select(); + break; case "editcharacter": case "editchar": GameMain.EditCharacterScreen.Select(); diff --git a/Subsurface/Source/GUI/GUIButton.cs b/Subsurface/Source/GUI/GUIButton.cs index 235bbecbf..8973d95eb 100644 --- a/Subsurface/Source/GUI/GUIButton.cs +++ b/Subsurface/Source/GUI/GUIButton.cs @@ -63,8 +63,8 @@ namespace Barotrauma } set { - if (textBlock == null) return; base.Font = value; + if (textBlock != null) textBlock.Font = value; } } diff --git a/Subsurface/Source/GameSession/CrewManager.cs b/Subsurface/Source/GameSession/CrewManager.cs index c81d87ffb..e7c30ad55 100644 --- a/Subsurface/Source/GameSession/CrewManager.cs +++ b/Subsurface/Source/GameSession/CrewManager.cs @@ -98,7 +98,8 @@ namespace Barotrauma name, Color.Transparent, Color.White, Alignment.Left, Alignment.Left, - null, frame); + null, frame, false); + textBlock.Font = GUI.SmallFont; textBlock.Padding = new Vector4(5.0f, 0.0f, 5.0f, 0.0f); new GUIImage(new Rectangle(-10, -10, 0, 0), character.AnimController.Limbs[0].sprite, Alignment.Left, frame); diff --git a/Subsurface/Source/GameSession/GameModes/SinglePlayerMode.cs b/Subsurface/Source/GameSession/GameModes/SinglePlayerMode.cs index 5178374bb..5a6fe2582 100644 --- a/Subsurface/Source/GameSession/GameModes/SinglePlayerMode.cs +++ b/Subsurface/Source/GameSession/GameModes/SinglePlayerMode.cs @@ -52,6 +52,7 @@ namespace Barotrauma CargoManager = new CargoManager(); endShiftButton = new GUIButton(new Rectangle(GameMain.GraphicsWidth - 220, 20, 200, 25), "End shift", Alignment.TopLeft, GUI.Style); + endShiftButton.Font = GUI.SmallFont; endShiftButton.OnClicked = EndShift; for (int i = 0; i < 3; i++) @@ -142,14 +143,12 @@ namespace Barotrauma if (Level.Loaded.AtEndPosition) { - endShiftButton.Text = "Enter " + Map.SelectedLocation.Name; - endShiftButton.Font = GUI.SmallFont; + endShiftButton.Text = "Enter " + Map.SelectedLocation.Name; endShiftButton.Draw(spriteBatch); } else if (Level.Loaded.AtStartPosition) { endShiftButton.Text = "Enter " + Map.CurrentLocation.Name; - endShiftButton.Font = GUI.SmallFont; endShiftButton.Draw(spriteBatch); } diff --git a/Subsurface/Source/GameSession/GameModes/TutorialMode.cs b/Subsurface/Source/GameSession/GameModes/TutorialMode.cs index 96d6fec8b..b9854f2ff 100644 --- a/Subsurface/Source/GameSession/GameModes/TutorialMode.cs +++ b/Subsurface/Source/GameSession/GameModes/TutorialMode.cs @@ -50,16 +50,10 @@ namespace Barotrauma Character character = Character.Create(charInfo, wayPoint.SimPosition); Character.Controlled = character; character.GiveJobItems(null); - - foreach (Item item in character.Inventory.items) - { - if (item == null || item.Name != "ID Card") continue; - item.AddTag("com"); - item.AddTag("eng"); - - break; - } + var idCard = character.Inventory.FindItem("ID Card"); + idCard.AddTag("com"); + idCard.AddTag("eng"); CrewManager.AddCharacter(character); @@ -495,7 +489,7 @@ namespace Barotrauma do { - var weldingTool = Character.Controlled.Inventory.items.FirstOrDefault(i => i != null && i.Name == "Welding Tool"); + var weldingTool = Character.Controlled.Inventory.Items.FirstOrDefault(i => i != null && i.Name == "Welding Tool"); if (weldingTool != null && weldingTool.ContainedItems.FirstOrDefault(contained => contained != null && contained.Name == "Welding Fuel Tank") != null) break; @@ -604,7 +598,7 @@ namespace Barotrauma private bool HasItem(string itemName) { if (Character.Controlled == null) return false; - return Character.Controlled.Inventory.items.FirstOrDefault(i => i != null && i.Name == itemName)!=null; + return Character.Controlled.Inventory.Items.FirstOrDefault(i => i != null && i.Name == itemName)!=null; } /// diff --git a/Subsurface/Source/Items/CharacterInventory.cs b/Subsurface/Source/Items/CharacterInventory.cs index 95c3fed58..8bdf72dfb 100644 --- a/Subsurface/Source/Items/CharacterInventory.cs +++ b/Subsurface/Source/Items/CharacterInventory.cs @@ -81,7 +81,7 @@ namespace Barotrauma public int FindLimbSlot(LimbSlot limbSlot) { - for (int i = 0; i < items.Length; i++) + for (int i = 0; i < Items.Length; i++) { if ( limbSlots[i] == limbSlot) return i; } @@ -90,9 +90,9 @@ namespace Barotrauma public bool IsInLimbSlot(Item item, LimbSlot limbSlot) { - for (int i = 0; i 4); + UpdateSlot(spriteBatch, slotRect, i, Items[i], i > 4); - if (draggingItem!=null && draggingItem == items[i]) draggingItemSlot = slotRect; + if (draggingItem!=null && draggingItem == Items[i]) draggingItemSlot = slotRect; } @@ -406,7 +406,7 @@ namespace Barotrauma bool multiSlot = false; //check if the item is in multiple slots - if (items[i] != null) + if (Items[i] != null) { slotRect.X = (int)slotPositions[i].X; slotRect.Y = (int)slotPositions[i].Y; @@ -415,7 +415,7 @@ namespace Barotrauma for (int n = 0; n < capacity; n++) { - if (items[n] != items[i]) continue; + if (Items[n] != Items[i]) continue; if (!multiSlot && i > n) break; @@ -430,7 +430,7 @@ namespace Barotrauma if (!multiSlot) continue; - UpdateSlot(spriteBatch, slotRect, i, items[i], i > 4); + UpdateSlot(spriteBatch, slotRect, i, Items[i], i > 4); //if (multiSlot && i == first) //{ @@ -469,7 +469,7 @@ namespace Barotrauma { for (int i = 0; i < capacity; i++) { - message.Write(items[i]==null ? (ushort)0 : (ushort)items[i].ID); + message.Write(Items[i]==null ? (ushort)0 : (ushort)Items[i].ID); } return true; @@ -486,14 +486,14 @@ namespace Barotrauma ushort itemId = message.ReadUInt16(); if (itemId==0) { - if (items[i] != null) items[i].Drop(character, false); + if (Items[i] != null) Items[i].Drop(character, false); } else { Item item = Entity.FindEntityByID(itemId) as Item; if (item == null) continue; - if (items[i] != item && items[i] != null) items[i].Drop(character, false); + if (Items[i] != item && Items[i] != null) Items[i].Drop(character, false); TryPutItem(item, i, false); } } diff --git a/Subsurface/Source/Items/Components/Door.cs b/Subsurface/Source/Items/Components/Door.cs index eb83c9986..c6e60c2d3 100644 --- a/Subsurface/Source/Items/Components/Door.cs +++ b/Subsurface/Source/Items/Components/Door.cs @@ -7,6 +7,7 @@ using FarseerPhysics.Factories; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using Barotrauma.Lights; +using System.Collections.Generic; namespace Barotrauma.Items.Components { @@ -41,8 +42,7 @@ namespace Barotrauma.Items.Components if (linkedGap != null) return linkedGap; foreach (MapEntity e in item.linkedTo) { - linkedGap = e as Gap; - linkedGap.ConnectedDoor = this; + linkedGap = e as Gap; if (linkedGap != null) return linkedGap; } linkedGap = new Gap(item.Rect); @@ -256,6 +256,30 @@ namespace Barotrauma.Items.Components linkedGap.Open = 1.0f; } + public List GetButtons() + { + ConnectionPanel connectionPanel = Item.GetComponent(); + if (connectionPanel == null) return new List(); + + List buttons = new List(); + + foreach (Connection c in connectionPanel.Connections) + { + foreach (Wire w in c.Wires) + { + if (w == null) continue; + var otherConnection = w.OtherConnection(c); + + if (otherConnection.Item == Item || otherConnection == null) continue; + + var controller = otherConnection.Item.GetComponent(); + if (controller != null) buttons.Add(controller); + } + } + + return buttons; + } + public override void Draw(SpriteBatch spriteBatch, bool editing) { Color color = (item.IsSelected) ? Color.Green : Color.White; @@ -272,38 +296,43 @@ namespace Barotrauma.Items.Components if (openState == 1.0f) { body.Enabled = false; + return; + } + + spriteBatch.Draw(doorSprite.Texture, new Vector2(item.Rect.Center.X, -item.Rect.Y), + new Rectangle(doorSprite.SourceRect.X, (int)(doorSprite.size.Y * openState), + (int)doorSprite.size.X, (int)(doorSprite.size.Y * (1.0f - openState))), + color, 0.0f, doorSprite.Origin, 1.0f, SpriteEffects.None, doorSprite.Depth); + + if (openState == 0.0f) + { + body.Enabled = true; } else { - spriteBatch.Draw(doorSprite.Texture, new Vector2(item.Rect.Center.X, -item.Rect.Y), - new Rectangle(doorSprite.SourceRect.X, (int)(doorSprite.size.Y * openState), - (int)doorSprite.size.X, (int)(doorSprite.size.Y * (1.0f - openState))), - color, 0.0f, doorSprite.Origin, 1.0f, SpriteEffects.None, doorSprite.Depth); + //push characters out of the doorway when the door is closing/opening + Vector2 simPos = ConvertUnits.ToSimUnits(new Vector2(item.Rect.X, item.Rect.Y)); + Vector2 simSize = ConvertUnits.ToSimUnits(new Vector2(item.Rect.Width, + item.Rect.Height * (1.0f - openState))); - if (openState == 0.0f) + foreach (Character c in Character.CharacterList) { - body.Enabled = true; - } - else - { - //push characters out of the doorway when the door is closing/opening - Vector2 simPos = ConvertUnits.ToSimUnits(new Vector2(item.Rect.X, item.Rect.Y)); - Vector2 simSize = ConvertUnits.ToSimUnits(new Vector2(item.Rect.Width, - item.Rect.Height * (1.0f - openState))); - - foreach (Character c in Character.CharacterList) + int dir = Math.Sign(c.AnimController.Limbs[0].SimPosition.X - simPos.X); + foreach (Limb l in c.AnimController.Limbs) { - int dir = Math.Sign(c.AnimController.Limbs[0].SimPosition.X - simPos.X); - foreach (Limb l in c.AnimController.Limbs) - { - if (l.SimPosition.Y < simPos.Y || l.SimPosition.Y > simPos.Y - simSize.Y) continue; - if (Math.Abs(l.SimPosition.X - simPos.X) > simSize.X * 2.0f) continue; + if (l.SimPosition.Y < simPos.Y || l.SimPosition.Y > simPos.Y - simSize.Y) continue; + if (Math.Abs(l.SimPosition.X - simPos.X) > simSize.X * 2.0f) continue; - l.body.ApplyForce(new Vector2(dir * 10.0f, 0.0f)); - } + l.body.ApplyForce(new Vector2(dir * 10.0f, 0.0f)); } } } + + } + + public override void OnMapLoaded() + { + LinkedGap.ConnectedDoor = this; } public override void Remove() diff --git a/Subsurface/Source/Items/Components/ItemComponent.cs b/Subsurface/Source/Items/Components/ItemComponent.cs index 2550ce4b6..7f4f750f8 100644 --- a/Subsurface/Source/Items/Components/ItemComponent.cs +++ b/Subsurface/Source/Items/Components/ItemComponent.cs @@ -551,7 +551,7 @@ namespace Barotrauma.Items.Components } if (!hasItem && ri.Type.HasFlag(RelatedItem.RelationType.Picked)) { - if (character.Inventory.items.FirstOrDefault(x => x!=null && x.Condition>0.0f && ri.MatchesItem(x))!=null) hasItem = true; + if (character.Inventory.Items.FirstOrDefault(x => x!=null && x.Condition>0.0f && ri.MatchesItem(x))!=null) hasItem = true; } if (!hasItem) { diff --git a/Subsurface/Source/Items/Components/ItemContainer.cs b/Subsurface/Source/Items/Components/ItemContainer.cs index 3cb9cfad4..0babebb28 100644 --- a/Subsurface/Source/Items/Components/ItemContainer.cs +++ b/Subsurface/Source/Items/Components/ItemContainer.cs @@ -127,7 +127,7 @@ namespace Barotrauma.Items.Components { if (!hasStatusEffects) return; - foreach (Item contained in inventory.items) + foreach (Item contained in inventory.Items) { if (contained == null || contained.Condition <= 0.0f) continue; //if (contained.body != null) contained.body.Enabled = false; @@ -179,7 +179,7 @@ namespace Barotrauma.Items.Components currentRotation += item.body.Rotation; } - foreach (Item containedItem in inventory.items) + foreach (Item containedItem in inventory.Items) { if (containedItem == null) continue; @@ -243,7 +243,7 @@ namespace Barotrauma.Items.Components { base.Remove(); - foreach (Item item in inventory.items) + foreach (Item item in inventory.Items) { if (item == null) continue; item.Remove(); @@ -274,10 +274,10 @@ namespace Barotrauma.Items.Components { XElement componentElement = base.Save(parentElement); - string[] itemIdStrings = new string[inventory.items.Length]; - for (int i = 0; i < inventory.items.Length; i++) + string[] itemIdStrings = new string[inventory.Items.Length]; + for (int i = 0; i < inventory.Items.Length; i++) { - itemIdStrings[i] = (inventory.items[i]==null) ? "0" : inventory.items[i].ID.ToString(); + itemIdStrings[i] = (inventory.Items[i]==null) ? "0" : inventory.Items[i].ID.ToString(); } componentElement.Add(new XAttribute("contained", string.Join(",",itemIdStrings))); diff --git a/Subsurface/Source/Items/Components/Machines/Fabricator.cs b/Subsurface/Source/Items/Components/Machines/Fabricator.cs index ffde50cc3..70b302f71 100644 --- a/Subsurface/Source/Items/Components/Machines/Fabricator.cs +++ b/Subsurface/Source/Items/Components/Machines/Fabricator.cs @@ -162,7 +162,7 @@ namespace Barotrauma.Items.Components ItemContainer container = item.GetComponent(); foreach (ItemPrefab ip in fabricatedItem.RequiredItems) { - var requiredItem = Array.Find(container.inventory.items, it => it != null && it.Prefab == ip); + var requiredItem = container.inventory.Items.FirstOrDefault(it => it != null && it.Prefab == ip); container.inventory.RemoveItem(requiredItem); } @@ -182,7 +182,7 @@ namespace Barotrauma.Items.Components ItemContainer container = item.GetComponent(); foreach (ItemPrefab ip in targetItem.RequiredItems) { - if (Array.Find(container.inventory.items, it => it != null && it.Prefab == ip) != null) continue; + if (Array.Find(container.inventory.Items, it => it != null && it.Prefab == ip) != null) continue; selectedItemFrame.GetChild().Enabled = false; break; } diff --git a/Subsurface/Source/Items/Components/Turret.cs b/Subsurface/Source/Items/Components/Turret.cs index ff617ef98..142ce006c 100644 --- a/Subsurface/Source/Items/Components/Turret.cs +++ b/Subsurface/Source/Items/Components/Turret.cs @@ -139,12 +139,12 @@ namespace Barotrauma.Items.Components ItemContainer containerComponent = projectileContainer.GetComponent(); if (containerComponent == null) continue; - for (int i = 0; i < containerComponent.inventory.items.Length; i++) + for (int i = 0; i < containerComponent.inventory.Items.Length; i++) { - if (containerComponent.inventory.items[i] == null) continue; - if ((projectileComponent = containerComponent.inventory.items[i].GetComponent()) != null) + if (containerComponent.inventory.Items[i] == null) continue; + if ((projectileComponent = containerComponent.inventory.Items[i].GetComponent()) != null) { - projectile = containerComponent.inventory.items[i]; + projectile = containerComponent.inventory.Items[i]; break; } } diff --git a/Subsurface/Source/Items/FixRequirement.cs b/Subsurface/Source/Items/FixRequirement.cs index f740473be..99f7228d2 100644 --- a/Subsurface/Source/Items/FixRequirement.cs +++ b/Subsurface/Source/Items/FixRequirement.cs @@ -54,7 +54,7 @@ namespace Barotrauma GUIComponent component = reqFrame.children.Find(c => c.UserData as string == itemName); GUITextBlock text = component as GUITextBlock; - Item item = character.Inventory.items.FirstOrDefault(i => i !=null && (i.Name == itemName || i.HasTag(itemName))); + Item item = character.Inventory.FindItem(itemName); bool itemFound = (item != null); if (!itemFound) success = false; diff --git a/Subsurface/Source/Items/Inventory.cs b/Subsurface/Source/Items/Inventory.cs index 6f431a12b..33e73244a 100644 --- a/Subsurface/Source/Items/Inventory.cs +++ b/Subsurface/Source/Items/Inventory.cs @@ -42,7 +42,7 @@ namespace Barotrauma protected int selectedSlot; - public Item[] items; + public Item[] Items; public Inventory(Entity owner, int capacity, Vector2? centerPos = null, int slotsPerRow=5) { @@ -52,7 +52,7 @@ namespace Barotrauma this.slotsPerRow = slotsPerRow; - items = new Item[capacity]; + Items = new Item[capacity]; CenterPos = (centerPos==null) ? new Vector2(0.5f, 0.5f) : (Vector2)centerPos; } @@ -61,7 +61,7 @@ namespace Barotrauma { for (int i = 0; i < capacity; i++) { - if (items[i] == item) return i; + if (Items[i] == item) return i; } return -1; } @@ -71,12 +71,12 @@ namespace Barotrauma for (int i = 0; i < capacity; i++) { //item is already in the inventory! - if (items[i] == item) return -1; + if (Items[i] == item) return -1; } for (int i = 0; i < capacity; i++) { - if (items[i] == null) return i; + if (Items[i] == null) return i; } return -1; @@ -84,8 +84,8 @@ namespace Barotrauma public virtual bool CanBePut(Item item, int i) { - if (i < 0 || i >= items.Length) return false; - return (items[i] == null); + if (i < 0 || i >= Items.Length) return false; + return (Items[i] == null); } /// @@ -124,7 +124,7 @@ namespace Barotrauma if (item.inventory != null) item.inventory.RemoveItem(item); } - items[i] = item; + Items[i] = item; item.inventory = this; if (item.body != null) { @@ -134,13 +134,18 @@ namespace Barotrauma if (createNetworkEvent) new NetworkEvent(NetworkEventType.InventoryUpdate, Owner.ID, true, true); } + public Item FindItem(string itemName) + { + return Items.FirstOrDefault(i => i != null && (i.Name == itemName || i.HasTag(itemName))); + } + public void RemoveItem(Item item) { //go through the inventory and remove the item from all slots for (int n = 0; n < capacity; n++) { - if (items[n] != item) continue; - items[n] = null; + if (Items[n] != item) continue; + Items[n] = null; item.inventory = null; } } @@ -177,9 +182,9 @@ namespace Barotrauma slotRect.X = startX + (rectWidth + spacing) * (i % slotsPerRow); slotRect.Y = startY + (rectHeight + spacing) * ((int)Math.Floor((double)i / slotsPerRow)); - if (draggingItem == items[i]) draggingItemSlot = slotRect; + if (draggingItem == Items[i]) draggingItemSlot = slotRect; - UpdateSlot(spriteBatch, slotRect, i, items[i], false); + UpdateSlot(spriteBatch, slotRect, i, Items[i], false); } if (draggingItem != null && !draggingItemSlot.Contains(PlayerInput.MousePosition) && draggingItem.container == this.Owner) @@ -247,7 +252,7 @@ namespace Barotrauma { #if DEBUG - System.Diagnostics.Debug.Assert(slotIndex >= 0 && slotIndex < items.Length); + System.Diagnostics.Debug.Assert(slotIndex >= 0 && slotIndex < Items.Length); #else if (slotIndex<0 || slotIndex>=items.Length) return; #endif @@ -266,7 +271,7 @@ namespace Barotrauma GUI.DrawRectangle(spriteBatch, containerRect, Color.White); Item[] containedItems = null; - if (items[slotIndex] != null) containedItems = items[slotIndex].ContainedItems; + if (Items[slotIndex] != null) containedItems = Items[slotIndex].ContainedItems; if (containedItems != null) { @@ -316,7 +321,7 @@ namespace Barotrauma public virtual bool FillNetworkData(NetworkEventType type, NetBuffer message, object data) { - var foundItems = Array.FindAll(items, i => i != null); + var foundItems = Array.FindAll(Items, i => i != null); message.Write((byte)foundItems.Count()); foreach (Item item in foundItems) { @@ -340,10 +345,10 @@ namespace Barotrauma for (int i = 0; i < capacity; i++) { - if (items[i] == null) continue; - if (!newItemIDs.Contains(items[i].ID)) + if (Items[i] == null) continue; + if (!newItemIDs.Contains(Items[i].ID)) { - items[i].Drop(null, false); + Items[i].Drop(null, false); continue; } } diff --git a/Subsurface/Source/Items/Item.cs b/Subsurface/Source/Items/Item.cs index 3a9e957a5..7609969bc 100644 --- a/Subsurface/Source/Items/Item.cs +++ b/Subsurface/Source/Items/Item.cs @@ -219,7 +219,7 @@ namespace Barotrauma get { ItemContainer c = GetComponent(); - return (c == null) ? null : Array.FindAll(c.inventory.items, i=>i!=null); + return (c == null) ? null : Array.FindAll(c.inventory.Items, i=>i!=null); } } diff --git a/Subsurface/Source/Items/ItemInventory.cs b/Subsurface/Source/Items/ItemInventory.cs index 3acbf3209..712f46c97 100644 --- a/Subsurface/Source/Items/ItemInventory.cs +++ b/Subsurface/Source/Items/ItemInventory.cs @@ -25,14 +25,14 @@ namespace Barotrauma for (int i = 0; i < capacity; i++) { //item is already in the inventory! - if (items[i] == item) return -1; + if (Items[i] == item) return -1; } if (!container.CanBeContained(item)) return -1; for (int i = 0; i < capacity; i++) { - if (items[i] == null) return i; + if (Items[i] == null) return i; } return -1; @@ -40,8 +40,8 @@ namespace Barotrauma public override bool CanBePut(Item item, int i) { - if (i < 0 || i >= items.Length) return false; - return (item!=null && items[i]==null && container.CanBeContained(item)); + if (i < 0 || i >= Items.Length) return false; + return (item!=null && Items[i]==null && container.CanBeContained(item)); } public override bool TryPutItem(Item item, int i, bool createNetworkEvent) diff --git a/Subsurface/Source/Items/ItemPrefab.cs b/Subsurface/Source/Items/ItemPrefab.cs index 76c2658d2..8f9bd920d 100644 --- a/Subsurface/Source/Items/ItemPrefab.cs +++ b/Subsurface/Source/Items/ItemPrefab.cs @@ -161,8 +161,8 @@ namespace Barotrauma name = ToolBox.GetAttributeString(element, "name", ""); if (name == "") DebugConsole.ThrowError("Unnamed item in "+filePath+"!"); - pickThroughWalls = ToolBox.GetAttributeBool(element, "pickthroughwalls", false); - pickDistance = ConvertUnits.ToSimUnits(ToolBox.GetAttributeFloat(element, "pickdistance", 0.0f)); + pickThroughWalls = ToolBox.GetAttributeBool(element, "pickthroughwalls", false); + pickDistance = ConvertUnits.ToSimUnits(ToolBox.GetAttributeFloat(element, "pickdistance", 0.0f)); isLinkable = ToolBox.GetAttributeBool(element, "linkable", false); diff --git a/Subsurface/Source/Items/RelatedItem.cs b/Subsurface/Source/Items/RelatedItem.cs index 2bccf83cc..c0c9db549 100644 --- a/Subsurface/Source/Items/RelatedItem.cs +++ b/Subsurface/Source/Items/RelatedItem.cs @@ -93,7 +93,7 @@ namespace Barotrauma break; case RelationType.Picked: if (character == null || character.Inventory==null) return false; - foreach (Item pickedItem in character.Inventory.items) + foreach (Item pickedItem in character.Inventory.Items) { if (pickedItem == null) continue; diff --git a/Subsurface/Source/Map/Map.cs b/Subsurface/Source/Map/Map.cs index 9e7e68a5e..1a9c9a407 100644 --- a/Subsurface/Source/Map/Map.cs +++ b/Subsurface/Source/Map/Map.cs @@ -328,7 +328,16 @@ namespace Barotrauma Location location = locations[i]; Vector2 pos = rectCenter + (location.MapPosition + offset) * scale; - if (!rect.Contains(pos)) continue; + + + + + Rectangle drawRect = location.Type.Sprite.SourceRect; + Rectangle sourceRect = drawRect; + drawRect.X = (int)pos.X - drawRect.Width/2; + drawRect.Y = (int)pos.Y - drawRect.Width/2; + + if (!rect.Intersects(drawRect)) continue; Color color = location.Connections.Find(c => c.Locations.Contains(currentLocation))==null ? Color.White : Color.Green; @@ -336,16 +345,32 @@ namespace Barotrauma if (location == currentLocation) color = Color.Orange; - location.Type.Sprite.Draw(spriteBatch, pos, color, 0.0f, scale/3.0f); + if (drawRect.X < rect.X) + { + sourceRect.X += rect.X - drawRect.X; + sourceRect.Width -= sourceRect.X; + drawRect.X = rect.X; + } + else if (drawRect.Right > rect.Right) + { + sourceRect.Width -= (drawRect.Right - rect.Right); + } - //int imgIndex = i % 16; - //int xCell = imgIndex % 4; - //int yCell = (int)Math.Floor(imgIndex / 4.0f); - //spriteBatch.Draw(iceCraters, pos, - // new Rectangle(xCell * 64, yCell * 64, 64, 64), - // Color.White, i, - // new Vector2(32, 32), 0.5f*scale, SpriteEffects.None, 0.0f); + if (drawRect.Y < rect.Y) + { + sourceRect.Y += rect.Y - drawRect.Y; + sourceRect.Height -= sourceRect.Y; + drawRect.Y = rect.Y; + } + else if (drawRect.Bottom > rect.Bottom) + { + sourceRect.Height -= drawRect.Bottom - rect.Bottom; + } + drawRect.Width = sourceRect.Width; + drawRect.Height = sourceRect.Height; + + spriteBatch.Draw(location.Type.Sprite.Texture, drawRect, sourceRect, color); } for (int i = 0; i < 3; i++ ) diff --git a/Subsurface/Source/Map/Submarine.cs b/Subsurface/Source/Map/Submarine.cs index a05debddb..9fd5853ed 100644 --- a/Subsurface/Source/Map/Submarine.cs +++ b/Subsurface/Source/Map/Submarine.cs @@ -636,6 +636,8 @@ namespace Barotrauma } } + WayPoint.GenerateSubWaypoints(); + GameMain.LightManager.OnMapLoaded(); ID = ushort.MaxValue-10; diff --git a/Subsurface/Source/Map/WayPoint.cs b/Subsurface/Source/Map/WayPoint.cs index d825fc3bd..b34ba97af 100644 --- a/Subsurface/Source/Map/WayPoint.cs +++ b/Subsurface/Source/Map/WayPoint.cs @@ -23,12 +23,19 @@ namespace Barotrauma //only characters with this job will be spawned at the waypoint private JobPrefab assignedJob; + private Hull currentHull; + public Gap ConnectedGap { get; private set; } + public Hull CurrentHull + { + get { return currentHull; } + } + public SpawnType SpawnType { get { return spawnType; } @@ -396,10 +403,14 @@ namespace Barotrauma return assignedWayPoints; } + public override void OnMapLoaded() + { + currentHull = Hull.FindHull(this.Position); + } public override XElement Save(XDocument doc) { - if (MoveWithLevel) return null; + if (MoveWithLevel || spawnType == SpawnType.Path) return null; XElement element = new XElement("WayPoint"); element.Add(new XAttribute("ID", ID), diff --git a/Subsurface/Source/Physics/PhysicsBody.cs b/Subsurface/Source/Physics/PhysicsBody.cs index 1e42e05a9..cb01c7a18 100644 --- a/Subsurface/Source/Physics/PhysicsBody.cs +++ b/Subsurface/Source/Physics/PhysicsBody.cs @@ -315,8 +315,6 @@ namespace Barotrauma sprite.Draw(spriteBatch, new Vector2(drawPosition.X, -drawPosition.Y), color, -drawRotation, 1.0f, spriteEffect, depth); - //prevPosition = body.Position; - //prevRotation = body.Rotation; } /// @@ -331,20 +329,6 @@ namespace Barotrauma float torque = body.Mass * angle * 60.0f * (force/100.0f); body.ApplyTorque(torque); - - //float nextAngle = bodyAngle + body->GetAngularVelocity() / 60.0; - //float totalRotation = desiredAngle - nextAngle; - //while (totalRotation < -180 * DEGTORAD) totalRotation += 360 * DEGTORAD; - //while (totalRotation > 180 * DEGTORAD) totalRotation -= 360 * DEGTORAD; - //float desiredAngularVelocity = totalRotation * 60; - //float torque = body->GetInertia() * desiredAngularVelocity / (1 / 60.0); - //body->ApplyTorque(torque); - - - - - //body.ApplyTorque((Math.Sign(angle) + Math.Max(Math.Min(angle * force, force / 2.0f), -force / 2.0f)) * body.Mass); - //body.ApplyTorque(-body.AngularVelocity * 0.5f * body.Mass); } @@ -352,53 +336,7 @@ namespace Barotrauma { list.Remove(this); GameMain.World.RemoveBody(body); - } - public void FillNetworkData(NetworkEventType type, NetOutgoingMessage message) - { - message.Write(body.Position.X); - message.Write(body.Position.Y); - message.Write(body.LinearVelocity.X); - message.Write(body.LinearVelocity.Y); - - message.Write(body.Rotation); - message.Write(body.AngularVelocity); - } - - public void ReadNetworkData(NetworkEventType type, NetIncomingMessage message) - { - Vector2 newTargetPos = Vector2.Zero; - Vector2 newTargetVel = Vector2.Zero; - - float newTargetRotation = 0.0f, newTargetAngularVel = 0.0f; - try - { - newTargetPos = new Vector2(message.ReadFloat(),message.ReadFloat()); - newTargetVel = new Vector2(message.ReadFloat(),message.ReadFloat()); - - newTargetRotation = message.ReadFloat(); - newTargetAngularVel = message.ReadFloat(); - } - - catch (Exception e) - { -#if DEBUG - DebugConsole.ThrowError("invalid network message", e); -#endif - return; - } - - if (!MathUtils.IsValid(newTargetPos) || !MathUtils.IsValid(newTargetVel) || - !MathUtils.IsValid(newTargetRotation) || !MathUtils.IsValid(newTargetAngularVel)) return; - - targetPosition = newTargetPos; - targetVelocity = newTargetVel; - - targetRotation = newTargetRotation; - targetAngularVelocity = newTargetAngularVel; - - - } } } diff --git a/Subsurface/Source/Screens/EditMapScreen.cs b/Subsurface/Source/Screens/EditMapScreen.cs index 7ff101292..c55633494 100644 --- a/Subsurface/Source/Screens/EditMapScreen.cs +++ b/Subsurface/Source/Screens/EditMapScreen.cs @@ -181,7 +181,7 @@ namespace Barotrauma } else if (dummyCharacter != null) { - foreach (Item item in dummyCharacter.Inventory.items) + foreach (Item item in dummyCharacter.Inventory.Items) { if (item == null) continue; diff --git a/Subsurface_Solution.v12.suo b/Subsurface_Solution.v12.suo index 54ca7c8c8..1bffe684d 100644 Binary files a/Subsurface_Solution.v12.suo and b/Subsurface_Solution.v12.suo differ