diff --git a/Subsurface/Barotrauma.csproj b/Subsurface/Barotrauma.csproj index 6b0ea2803..dd85d1914 100644 --- a/Subsurface/Barotrauma.csproj +++ b/Subsurface/Barotrauma.csproj @@ -60,6 +60,7 @@ + @@ -598,6 +599,9 @@ PreserveNewest + + PreserveNewest + PreserveNewest diff --git a/Subsurface/Content/Map/beaconbackground.jpg b/Subsurface/Content/Map/beaconbackground.jpg index 179b69a7b..abe7ff4ee 100644 Binary files a/Subsurface/Content/Map/beaconbackground.jpg and b/Subsurface/Content/Map/beaconbackground.jpg differ diff --git a/Subsurface/Content/Map/locationTypes.xml b/Subsurface/Content/Map/locationTypes.xml index d51b53400..530832341 100644 --- a/Subsurface/Content/Map/locationTypes.xml +++ b/Subsurface/Content/Map/locationTypes.xml @@ -12,9 +12,15 @@ + + + + + + + + + + + + + + + background="Content/Map/researchbackground.jpg"> + + + + + + + i.components.Find(ic => ic.GetType() == order.ItemComponentType) != null); + int y2 = y; + foreach (Item it in matchingItems) + { + var newOrder = new Order(order, it.components.Find(ic => ic.GetType() == order.ItemComponentType)); + + var button = new GUIButton(new Rectangle(x, y2, 150, 20), order.Name, GUI.Style, frame); + button.UserData = newOrder; + button.OnClicked = SetOrder; + y2 += 25; + } + } + else + { + var button = new GUIButton(new Rectangle(x, y, 150, 20), order.Name, GUI.Style, frame); + button.UserData = order; + button.OnClicked = SetOrder; + } + + + + x += 160; + } + } + + public void UpdateCharacters() + { + if (frame == null) CreateGUIFrame(); + + List prevCharacterFrames = new List(); + foreach (GUIComponent child in frame.children) + { + if (child.UserData as Character == null) continue; + + prevCharacterFrames.Add(child); + } + + foreach (GUIComponent child in prevCharacterFrames) + { + frame.RemoveChild(child); + } + int x = 0, y = 0; foreach (Character character in crewManager.characters) { - GUIButton characterButton = new GUIButton(new Rectangle(x,y, 150, 40), "", Color.Transparent, null, frame); + if (character.IsDead) continue; + + GUIButton characterButton = new GUIButton(new Rectangle(x, y, 150, 40), "", Color.Transparent, null, frame); characterButton.UserData = character; characterButton.Padding = new Vector4(5.0f, 5.0f, 5.0f, 5.0f); - - + if (character == Character.Controlled) { characterButton.CanBeSelected = false; @@ -75,18 +130,7 @@ namespace Barotrauma new GUIImage(new Rectangle(-10, -5, 0, 0), character.AnimController.Limbs[0].sprite, Alignment.Left, characterButton); - x += 160; - } - - x = 0; - y = 150; - foreach (Order command in Order.List) - { - var button = new GUIButton(new Rectangle(x, y, 150, 20), command.Name, GUI.Style, frame); - button.UserData = command; - button.OnClicked = SetOrder; - - x += button.Rect.Width + 10; + x += 160; } } diff --git a/Subsurface/Source/Characters/AI/HumanAIController.cs b/Subsurface/Source/Characters/AI/HumanAIController.cs index 961025d0e..7032a4502 100644 --- a/Subsurface/Source/Characters/AI/HumanAIController.cs +++ b/Subsurface/Source/Characters/AI/HumanAIController.cs @@ -50,7 +50,7 @@ namespace Barotrauma //{ // 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.InWater) diff --git a/Subsurface/Source/Characters/AI/Objectives/AIObjective.cs b/Subsurface/Source/Characters/AI/Objectives/AIObjective.cs index 5da96ddf8..48d815f6c 100644 --- a/Subsurface/Source/Characters/AI/Objectives/AIObjective.cs +++ b/Subsurface/Source/Characters/AI/Objectives/AIObjective.cs @@ -13,6 +13,8 @@ namespace Barotrauma protected Character character; + protected string option; + public virtual bool IsCompleted() { return false; @@ -23,11 +25,23 @@ namespace Barotrauma get { return false; } } - public AIObjective(Character character) + public string Option + { + get { return option; } + } + + + public AIObjective(Character character, string option) { subObjectives = new List(); this.character = character; + + this.option = option; + +#if DEBUG + IsDuplicate(null); +#endif } /// @@ -37,10 +51,10 @@ namespace Barotrauma /// the character who's trying to achieve the objective public void TryComplete(float deltaTime) { + subObjectives.RemoveAll(s => s.IsCompleted()); + foreach (AIObjective objective in subObjectives) { - if (objective.IsCompleted()) continue; - objective.TryComplete(deltaTime); return; } @@ -50,6 +64,13 @@ namespace Barotrauma protected virtual void Act(float deltaTime) { } + public void AddSubObjective(AIObjective objective) + { + if (subObjectives.Find(o => o.IsDuplicate(objective)) != null) return; + + subObjectives.Add(objective); + } + public virtual float GetPriority(Character character) { return 0.0f; @@ -57,7 +78,12 @@ namespace Barotrauma public virtual bool IsDuplicate(AIObjective otherObjective) { +#if DEBUG throw new NotImplementedException(); +#else + return (this.GetType() == otherObjective.GetType()); +#endif + } } } diff --git a/Subsurface/Source/Characters/AI/Objectives/AIObjectiveContainItem.cs b/Subsurface/Source/Characters/AI/Objectives/AIObjectiveContainItem.cs new file mode 100644 index 000000000..a6f65822a --- /dev/null +++ b/Subsurface/Source/Characters/AI/Objectives/AIObjectiveContainItem.cs @@ -0,0 +1,73 @@ +using Barotrauma.Items.Components; +using Microsoft.Xna.Framework; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Barotrauma +{ + class AIObjectiveContainItem: AIObjective + { + private string itemName; + + private ItemContainer container; + + bool canBeCompleted; + + bool isCompleted; + + + public AIObjectiveContainItem(Character character, string itemName, ItemContainer container) + : base (character, "") + { + this.itemName = itemName; + this.container = container; + + //check if the container has room for more items + canBeCompleted = false; + foreach (Item contained in container.inventory.Items) + { + if (contained != null) continue; + canBeCompleted = true; + break; + } + } + + public override bool IsCompleted() + { + return isCompleted; + } + + protected override void Act(float deltaTime) + { + if (isCompleted) return; + + //get the item that should be contained + var itemToContain = character.Inventory.FindItem(itemName); + if (itemToContain == null) + { + AddSubObjective(new AIObjectiveGetItem(character, itemName)); + return; + } + + if (Vector2.Distance(character.SimPosition, container.Item.SimPosition) > container.Item.PickDistance + || !container.Item.IsInsideTrigger(character.Position)) + { + AddSubObjective(new AIObjectiveGoTo(container.Item.SimPosition, character)); + return; + } + + container.Combine(itemToContain); + isCompleted = true; + } + + public override bool IsDuplicate(AIObjective otherObjective) + { + AIObjectiveContainItem objective = otherObjective as AIObjectiveContainItem; + return (objective != null); + } + + + } +} diff --git a/Subsurface/Source/Characters/AI/Objectives/AIObjectiveFindSafety.cs b/Subsurface/Source/Characters/AI/Objectives/AIObjectiveFindSafety.cs index 2fec74906..b796169b5 100644 --- a/Subsurface/Source/Characters/AI/Objectives/AIObjectiveFindSafety.cs +++ b/Subsurface/Source/Characters/AI/Objectives/AIObjectiveFindSafety.cs @@ -8,21 +8,21 @@ namespace Barotrauma { class AIObjectiveFindSafety : AIObjective { - const float SearchHullInterval = 1.0f; + const float SearchHullInterval = 3.0f; const float MinSafety = 50.0f; AIObjectiveGoTo gotoObjective; - private List unreachable; + private List unreachable; float currenthullSafety; float searchHullTimer; public AIObjectiveFindSafety(Character character) - : base(character) + : base(character, "") { - unreachable = new List(); + unreachable = new List(); } protected override void Act(float deltaTime) @@ -44,6 +44,7 @@ namespace Barotrauma } else { + var pathSteering = character.AIController.SteeringManager as IndoorsSteeringManager; Hull bestHull = null; float bestValue = currenthullSafety; @@ -51,7 +52,7 @@ namespace Barotrauma foreach (Hull hull in Hull.hullList) { if (hull == character.AnimController.CurrentHull) continue; - if (unreachable.Contains(hull.AiTarget)) continue; + if (unreachable.Contains(hull)) continue; float hullValue = GetHullSafety(hull); hullValue -= (float)Math.Sqrt(Math.Abs(character.Position.X- hull.Position.X)); @@ -66,7 +67,17 @@ namespace Barotrauma if (bestHull != null) { - gotoObjective = new AIObjectiveGoTo(bestHull.AiTarget, character); + var path = pathSteering.PathFinder.FindPath(character.SimPosition, bestHull.SimPosition); + if (pathSteering.CurrentPath != null && pathSteering.CurrentPath.Cost < path.Cost && !pathSteering.CurrentPath.Unreachable && gotoObjective!=null) + { + return; + } + else + { + pathSteering.SetPath(path); + } + + gotoObjective = new AIObjectiveGoTo(bestHull, character); //character.AIController.SelectTarget(bestHull.AiTarget); } @@ -80,7 +91,7 @@ namespace Barotrauma if (pathSteering!=null && pathSteering.CurrentPath!= null && pathSteering.CurrentPath.Unreachable && !unreachable.Contains(gotoObjective.Target)) { - unreachable.Add(gotoObjective.Target); + unreachable.Add(gotoObjective.Target as Hull); } } diff --git a/Subsurface/Source/Characters/AI/Objectives/AIObjectiveFixLeak.cs b/Subsurface/Source/Characters/AI/Objectives/AIObjectiveFixLeak.cs index 0d23d7de4..0d4011b9e 100644 --- a/Subsurface/Source/Characters/AI/Objectives/AIObjectiveFixLeak.cs +++ b/Subsurface/Source/Characters/AI/Objectives/AIObjectiveFixLeak.cs @@ -11,7 +11,7 @@ namespace Barotrauma Gap leak; public AIObjectiveFixLeak(Gap leak, Character character) - :base (character) + :base (character, "") { this.leak = leak; } diff --git a/Subsurface/Source/Characters/AI/Objectives/AIObjectiveGetItem.cs b/Subsurface/Source/Characters/AI/Objectives/AIObjectiveGetItem.cs index f2e1dc6ba..1b0c36abe 100644 --- a/Subsurface/Source/Characters/AI/Objectives/AIObjectiveGetItem.cs +++ b/Subsurface/Source/Characters/AI/Objectives/AIObjectiveGetItem.cs @@ -22,7 +22,7 @@ namespace Barotrauma } public AIObjectiveGetItem(Character character, string itemName) - : base (character) + : base (character, "") { canBeCompleted = true; @@ -72,7 +72,7 @@ namespace Barotrauma public override bool IsCompleted() { - return character.Inventory.Items.FirstOrDefault(i => i != null && (i.HasTag(itemName) || i.Name == itemName)) != null; + return character.Inventory.FindItem(itemName) != null; } } } diff --git a/Subsurface/Source/Characters/AI/Objectives/AIObjectiveGoTo.cs b/Subsurface/Source/Characters/AI/Objectives/AIObjectiveGoTo.cs index 48621d21b..60fcc020a 100644 --- a/Subsurface/Source/Characters/AI/Objectives/AIObjectiveGoTo.cs +++ b/Subsurface/Source/Characters/AI/Objectives/AIObjectiveGoTo.cs @@ -10,7 +10,7 @@ namespace Barotrauma { class AIObjectiveGoTo : AIObjective { - AITarget target; + Entity target; Vector2 targetPos; @@ -26,13 +26,13 @@ namespace Barotrauma } } - public AITarget Target + public Entity Target { get { return target; } } - public AIObjectiveGoTo(AITarget target, Character character, bool repeat = false) - : base (character) + public AIObjectiveGoTo(Entity target, Character character, bool repeat = false) + : base (character, "") { this.target = target; this.repeat = false; @@ -40,14 +40,19 @@ namespace Barotrauma public AIObjectiveGoTo(Vector2 targetPos, Character character) - : base(character) + : base(character, "") { this.targetPos = targetPos; } protected override void Act(float deltaTime) { - character.AIController.SelectTarget(target); + if (character.SelectedConstruction!=null) + { + character.SelectedConstruction = null; + } + + if (target!=null) character.AIController.SelectTarget(target.AiTarget); character.AIController.SteeringManager.SteeringSeek( target != null ? target.SimPosition : targetPos); @@ -56,7 +61,22 @@ namespace Barotrauma public override bool IsCompleted() { if (repeat) return false; - return Vector2.Distance(target != null ? target.SimPosition : ConvertUnits.ToDisplayUnits(targetPos), character.SimPosition) < 0.5f; + + float allowedDistance = 0.5f; + var item = target as Item; + if (item != null) allowedDistance = Math.Max(item.PickDistance,allowedDistance); + + return Vector2.Distance(target != null ? target.SimPosition : targetPos, character.SimPosition) < allowedDistance; + } + + public override bool IsDuplicate(AIObjective otherObjective) + { + AIObjectiveGoTo objective = otherObjective as AIObjectiveGoTo; + if (objective == null) return false; + + if (objective.target == target) return true; + + return (objective.targetPos == targetPos); } } } diff --git a/Subsurface/Source/Characters/AI/Objectives/AIObjectiveIdle.cs b/Subsurface/Source/Characters/AI/Objectives/AIObjectiveIdle.cs index 1d24d7f78..42f55569a 100644 --- a/Subsurface/Source/Characters/AI/Objectives/AIObjectiveIdle.cs +++ b/Subsurface/Source/Characters/AI/Objectives/AIObjectiveIdle.cs @@ -13,7 +13,7 @@ namespace Barotrauma - public AIObjectiveIdle(Character character) : base(character) + public AIObjectiveIdle(Character character) : base(character, "") { } @@ -26,10 +26,27 @@ namespace Barotrauma protected override void Act(float deltaTime) { + + var pathSteering = character.AIController.SteeringManager as IndoorsSteeringManager; + if (newTargetTimer <= 0.0f) { currentTarget = FindRandomTarget(); + if (currentTarget!=null) + { + var path = pathSteering.PathFinder.FindPath(character.SimPosition, currentTarget.SimPosition); + if (path.Cost > 200.0f) + { + return; + } + else + { + pathSteering.SetPath(path); + } + } + + newTargetTimer = currentTarget == null ? 5.0f : 10.0f; } else @@ -39,17 +56,27 @@ namespace Barotrauma if (currentTarget == null) return; - + + + //wander randomly if reached the end of the path or the target is unreachable + if (pathSteering!=null && pathSteering.CurrentPath != null && + (pathSteering.CurrentPath.NextNode == null || pathSteering.CurrentPath.Unreachable)) + { + if (character.Position.X < character.AnimController.CurrentHull.Rect.X + 200.0f) + { + pathSteering.SteeringManual(deltaTime, Vector2.UnitX); + } + else if (character.Position.X > character.AnimController.CurrentHull.Rect.Right - 200.0f) + { + pathSteering.SteeringManual(deltaTime, -Vector2.UnitX); + } + + character.AIController.SteeringManager.SteeringWander(1.0f); + 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() diff --git a/Subsurface/Source/Characters/AI/Objectives/AIObjectiveManager.cs b/Subsurface/Source/Characters/AI/Objectives/AIObjectiveManager.cs index d46b9f26b..01fd407b6 100644 --- a/Subsurface/Source/Characters/AI/Objectives/AIObjectiveManager.cs +++ b/Subsurface/Source/Characters/AI/Objectives/AIObjectiveManager.cs @@ -47,7 +47,7 @@ namespace Barotrauma public void UpdateObjectives() { - if (currentOrder != null || !objectives.Any()) return; + if (!objectives.Any()) return; //remove completed objectives objectives = objectives.FindAll(o => !o.IsCompleted()); @@ -69,7 +69,7 @@ namespace Barotrauma public void DoCurrentObjective(float deltaTime) { - if (currentOrder != null) + if (currentOrder != null && (!objectives.Any() || objectives[0].GetPriority(character) i.GetComponent() != null); - if (reactorItem == null) return; - - currentOrder = new AIObjectiveOperateItem(reactorItem.GetComponent(), character); + currentOrder = new AIObjectiveGoTo(Character.Controlled, character, true); break; default: - currentOrder = null; + if (order.TargetItem == null) return; + + currentOrder = new AIObjectiveOperateItem(order.TargetItem, character, option); + break; } } diff --git a/Subsurface/Source/Characters/AI/Objectives/AIObjectiveOperateItem.cs b/Subsurface/Source/Characters/AI/Objectives/AIObjectiveOperateItem.cs index 681189155..2421a5040 100644 --- a/Subsurface/Source/Characters/AI/Objectives/AIObjectiveOperateItem.cs +++ b/Subsurface/Source/Characters/AI/Objectives/AIObjectiveOperateItem.cs @@ -10,22 +10,43 @@ namespace Barotrauma class AIObjectiveOperateItem : AIObjective { private ItemComponent targetItem; + private ItemComponent itemController; - public AIObjectiveOperateItem(ItemComponent item, Character character) - :base (character) + private bool isCompleted; + + + + public AIObjectiveOperateItem(ItemComponent item, Character character, string option) + :base (character, option) { targetItem = item; + + var controllers = item.Item.GetConnectedComponents(); + if (controllers.Any()) itemController = controllers[0]; } protected override void Act(float deltaTime) { - if (Vector2.Distance(character.SimPosition, targetItem.Item.SimPosition) < targetItem.Item.PickDistance) + ItemComponent target = itemController == null ? targetItem: itemController; + + if (Vector2.Distance(character.SimPosition, target.Item.SimPosition) < target.Item.PickDistance + || target.Item.IsInsideTrigger(character.Position)) { - //targetItem.Pick(character, false, true); + if (character.SelectedConstruction != target.Item && target.CanBeSelected) + { + target.Item.Pick(character, false, true); + } + + if (targetItem.AIOperate(deltaTime, character, this)) isCompleted = true; return; } - subObjectives.Add(new AIObjectiveGoTo(targetItem.Item.SimPosition, character)); + subObjectives.Add(new AIObjectiveGoTo(target.Item, character)); + } + + public override bool IsCompleted() + { + return isCompleted; } public override bool IsDuplicate(AIObjective otherObjective) diff --git a/Subsurface/Source/Characters/AI/Order.cs b/Subsurface/Source/Characters/AI/Order.cs index 5f5532566..1f8ccc527 100644 --- a/Subsurface/Source/Characters/AI/Order.cs +++ b/Subsurface/Source/Characters/AI/Order.cs @@ -1,4 +1,5 @@ -using System; +using Barotrauma.Items.Components; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -7,32 +8,53 @@ namespace Barotrauma { class Order { - public static List List; + public static List PrefabList; public readonly string Name; public readonly string DoingText; - Sprite buttonSprite; + //Sprite buttonSprite; + + public readonly Type ItemComponentType; + + public ItemComponent TargetItem; public readonly string[] Options; static Order() { - List = new List(); + PrefabList = new List(); - new Order("Follow", "Following"); - new Order("Operate Reactor", "Operating reactor", new string[] {"Power Up", "Shutdown"}); + PrefabList.Add(new Order("Follow", "Following")); - new Order("Dismiss", "Dismissed"); + PrefabList.Add(new Order("Operate Reactor", "Operating reactor", typeof(Reactor), new string[] {"Power up", "Shutdown"})); + PrefabList.Add(new Order("Operate Railgun", "Operating railgun", typeof(Turret), new string[] { "Fire at will", "Hold fire" })); + + + PrefabList.Add(new Order("Dismiss", "Dismissed")); + } + + private Order(string name, string doingText, Type itemComponentType, string[] parameters = null) + { + Name = name; + DoingText = doingText; + ItemComponentType = itemComponentType; + Options = parameters == null ? new string[0] : parameters; + } + + public Order(Order prefab, ItemComponent targetItem) + { + Name = prefab.Name; + DoingText = prefab.DoingText; + ItemComponentType = prefab.ItemComponentType; + Options = prefab.Options; + + TargetItem = targetItem; } private Order(string name, string doingText, string[] parameters = null) + :this (name,doingText, null, parameters) { - this.Name = name; - this.DoingText = doingText; - this.Options = parameters == null ? new string[0] : parameters; - - List.Add(this); } } diff --git a/Subsurface/Source/Characters/AI/PathFinder.cs b/Subsurface/Source/Characters/AI/PathFinder.cs index 5af610785..9f8b8cb5d 100644 --- a/Subsurface/Source/Characters/AI/PathFinder.cs +++ b/Subsurface/Source/Characters/AI/PathFinder.cs @@ -266,6 +266,7 @@ namespace Barotrauma { finalPath.Add(pathNode.Waypoint); + path.Cost += pathNode.F; pathNode = pathNode.Parent; } @@ -275,6 +276,7 @@ namespace Barotrauma { path.AddNode(wayPoint); } + return path; } diff --git a/Subsurface/Source/Characters/AI/PathSteeringManager.cs b/Subsurface/Source/Characters/AI/PathSteeringManager.cs index fe3098496..2bdedfea9 100644 --- a/Subsurface/Source/Characters/AI/PathSteeringManager.cs +++ b/Subsurface/Source/Characters/AI/PathSteeringManager.cs @@ -49,6 +49,13 @@ namespace Barotrauma findPathTimer -= 1.0f / 60.0f; } + public void SetPath(SteeringPath path) + { + currentPath = path; + if (path.Nodes.Any()) currentTarget = path.Nodes[path.Nodes.Count - 1].SimPosition; + findPathTimer = 1.0f; + } + protected override Vector2 DoSteeringSeek(Vector2 target, float speed = 1) { @@ -101,7 +108,7 @@ namespace Barotrauma //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(); + var buttons = door.Item.GetConnectedComponents(); foreach (Controller controller in buttons) { if (Vector2.Distance(controller.Item.SimPosition, character.SimPosition) > controller.Item.PickDistance * 2.0f) continue; @@ -123,7 +130,7 @@ namespace Barotrauma if (!canOpenDoors) return null; - var doorButtons = nextNode.Waypoint.ConnectedGap.ConnectedDoor.GetButtons(); + var doorButtons = nextNode.Waypoint.ConnectedGap.ConnectedDoor.Item.GetConnectedComponents(); foreach (Controller button in doorButtons) { if (Math.Sign(button.Item.Position.X - nextNode.Waypoint.Position.X) != diff --git a/Subsurface/Source/Characters/AI/SteeringManager.cs b/Subsurface/Source/Characters/AI/SteeringManager.cs index a25896691..c931edc79 100644 --- a/Subsurface/Source/Characters/AI/SteeringManager.cs +++ b/Subsurface/Source/Characters/AI/SteeringManager.cs @@ -50,6 +50,11 @@ namespace Barotrauma steering += DoSteeringAvoid(deltaTime, speed); } + public void SteeringManual(float deltaTime, Vector2 velocity) + { + steering += velocity * deltaTime; + } + public virtual void Update(float speed = 1.0f) { float steeringSpeed = steering.Length(); @@ -111,7 +116,7 @@ namespace Barotrauma float maxDistance = 2.0f; - Vector2 ahead = host.SimPosition + Vector2.Normalize(host.Steering)*maxDistance; + Vector2 ahead = host.SimPosition + Vector2.Normalize(host.Steering) * maxDistance; if (rayCastTimer <= 0.0f) { @@ -120,12 +125,12 @@ namespace Barotrauma if (closestBody == null) { avoidSteering = Vector2.Zero; - return Vector2.Zero; + return Vector2.Zero; } else { Structure closestStructure = closestBody.UserData as Structure; - if (closestStructure!=null) + if (closestStructure != null) { Vector2 obstaclePosition = Submarine.LastPickedPosition; if (closestStructure.IsHorizontal) @@ -139,8 +144,14 @@ namespace Barotrauma avoidSteering = Vector2.Normalize(Submarine.LastPickedPosition - obstaclePosition); } + else + { + Item item = closestBody.UserData as Item; + if (item != null) avoidSteering = Vector2.Normalize(Submarine.LastPickedPosition - item.SimPosition); + + } } - + } else { @@ -148,7 +159,7 @@ namespace Barotrauma } return avoidSteering * speed; - } + } } diff --git a/Subsurface/Source/Characters/AI/SteeringPath.cs b/Subsurface/Source/Characters/AI/SteeringPath.cs index d508da2d8..428ba2af0 100644 --- a/Subsurface/Source/Characters/AI/SteeringPath.cs +++ b/Subsurface/Source/Characters/AI/SteeringPath.cs @@ -32,6 +32,12 @@ namespace Barotrauma get { return currentIndex; } } + public float Cost + { + get; + set; + } + public WayPoint PrevNode { get diff --git a/Subsurface/Source/Characters/Character.cs b/Subsurface/Source/Characters/Character.cs index 127d9c9d1..4b427422f 100644 --- a/Subsurface/Source/Characters/Character.cs +++ b/Subsurface/Source/Characters/Character.cs @@ -131,6 +131,11 @@ namespace Barotrauma public Vector2 CursorPosition { get { return cursorPosition; } + set + { + if (!MathUtils.IsValid(value)) return; + cursorPosition = value; + } } public Character ClosestCharacter diff --git a/Subsurface/Source/Characters/CharacterInfo.cs b/Subsurface/Source/Characters/CharacterInfo.cs index cc6b805d0..2845daf1d 100644 --- a/Subsurface/Source/Characters/CharacterInfo.cs +++ b/Subsurface/Source/Characters/CharacterInfo.cs @@ -216,6 +216,30 @@ namespace Barotrauma return frame; } + public GUIFrame CreateCharacterFrame(GUIComponent parent, string text, object userData) + { + GUIFrame frame = new GUIFrame(new Rectangle(0, 0, 0, 40), Color.Transparent, null, parent); + frame.UserData = userData; + frame.Padding = new Vector4(5.0f, 5.0f, 5.0f, 5.0f); + frame.HoverColor = Color.LightGray * 0.5f; + frame.SelectedColor = Color.Gold * 0.5f; + + // string name = character.Info.Name.Replace(' ', '\n'); + + GUITextBlock textBlock = new GUITextBlock( + new Rectangle(40, 0, 0, 25), + text, + Color.Transparent, Color.White, + Alignment.Left, Alignment.Left, + null, frame, false); + textBlock.Font = GUI.SmallFont; + textBlock.Padding = new Vector4(5.0f, 0.0f, 5.0f, 0.0f); + + new GUIImage(new Rectangle(-10, -5, 0, 0), HeadSprite, Alignment.Left, frame); + + return frame; + } + public void UpdateCharacterItems() { pickedItems.Clear(); diff --git a/Subsurface/Source/Characters/Jobs/Job.cs b/Subsurface/Source/Characters/Jobs/Job.cs index 24aad1fd9..6908e1223 100644 --- a/Subsurface/Source/Characters/Jobs/Job.cs +++ b/Subsurface/Source/Characters/Jobs/Job.cs @@ -44,11 +44,6 @@ namespace Barotrauma get { return skills.Values.ToList(); } } - //public List SkillLevels - //{ - // get { return skills.Values.ToList(); } - //} - public Job(JobPrefab jobPrefab) { prefab = jobPrefab; diff --git a/Subsurface/Source/Characters/Jobs/JobPrefab.cs b/Subsurface/Source/Characters/Jobs/JobPrefab.cs index 677635c36..aee18aac6 100644 --- a/Subsurface/Source/Characters/Jobs/JobPrefab.cs +++ b/Subsurface/Source/Characters/Jobs/JobPrefab.cs @@ -9,26 +9,7 @@ namespace Barotrauma class JobPrefab { public static List List; - - string name; - string description; - - //how many crew members can have the job (only one captain etc) - private int maxNumber; - - //how many crew members are REQUIRED to have a job - //(i.e. if one captain is required, one captain is chosen even if all the players have set captain to lowest preference) - private int minNumber; - - private float commonness; - - //if set to true, a client that has chosen this as their preferred job will get it no matter what - public bool AllowAlways - { - get; - private set; - } - + //names of the items the Character spawns with public List ItemNames; public List EquipItem; @@ -37,39 +18,55 @@ namespace Barotrauma public string Name { - get { return name; } + get; + private set; } public string Description { - get { return description; } + get; + private set; } + + //if set to true, a client that has chosen this as their preferred job will get it no matter what + public bool AllowAlways + { + get; + private set; + } + + //how many crew members can have the job (only one captain etc) public int MaxNumber { - get { return maxNumber; } + get; + private set; } + //how many crew members are REQUIRED to have the job + //(i.e. if one captain is required, one captain is chosen even if all the players have set captain to lowest preference) public int MinNumber { - get { return minNumber; } + get; + private set; } public float Commonness { - get { return commonness; } + get; + private set; } public JobPrefab(XElement element) { - name = ToolBox.GetAttributeString(element, "name", "name not found"); + Name = ToolBox.GetAttributeString(element, "name", "name not found"); - description = ToolBox.GetAttributeString(element, "description", ""); + Description = ToolBox.GetAttributeString(element, "description", ""); - minNumber = ToolBox.GetAttributeInt(element, "minnumber", 0); - maxNumber = ToolBox.GetAttributeInt(element, "maxnumber", 10); + MinNumber = ToolBox.GetAttributeInt(element, "minnumber", 0); + MaxNumber = ToolBox.GetAttributeInt(element, "maxnumber", 10); - commonness = ToolBox.GetAttributeInt(element, "commonness", 10); + Commonness = ToolBox.GetAttributeInt(element, "commonness", 10); AllowAlways = ToolBox.GetAttributeBool(element, "allowalways", false); @@ -117,9 +114,9 @@ namespace Barotrauma GUIFrame frame = new GUIFrame(new Rectangle(GameMain.GraphicsWidth / 2 - width / 2, GameMain.GraphicsHeight / 2 - height / 2, width, height), GUI.Style, backFrame); frame.Padding = new Vector4(30.0f, 30.0f, 30.0f, 30.0f); - new GUITextBlock(new Rectangle(0,0,100,20), name, GUI.Style, Alignment.TopLeft, Alignment.TopLeft, frame, false, GUI.LargeFont); + new GUITextBlock(new Rectangle(0,0,100,20), Name, GUI.Style, Alignment.TopLeft, Alignment.TopLeft, frame, false, GUI.LargeFont); - var descriptionBlock = new GUITextBlock(new Rectangle(0, 40, 0, 0), description, GUI.Style, Alignment.TopLeft, Alignment.TopLeft, frame, true, GUI.SmallFont); + var descriptionBlock = new GUITextBlock(new Rectangle(0, 40, 0, 0), Description, GUI.Style, Alignment.TopLeft, Alignment.TopLeft, frame, true, GUI.SmallFont); new GUITextBlock(new Rectangle(0, 40 + descriptionBlock.Rect.Height + 20, 100, 20), "Skills: ", GUI.Style, Alignment.TopLeft, Alignment.TopLeft, frame, false, GUI.LargeFont); diff --git a/Subsurface/Source/DebugConsole.cs b/Subsurface/Source/DebugConsole.cs index 8226cec06..54e6a579d 100644 --- a/Subsurface/Source/DebugConsole.cs +++ b/Subsurface/Source/DebugConsole.cs @@ -41,7 +41,10 @@ namespace Barotrauma public static bool IsOpen { - get { return isOpen; } + get + { + return isOpen; + } } public static void Init(GameWindow window) @@ -72,6 +75,7 @@ namespace Barotrauma } else { + GUIComponent.MouseOn = null; textBox.Deselect(); } @@ -80,10 +84,8 @@ namespace Barotrauma if (isOpen) { - frame.Update(deltaTime); - Character.DisableControls = true; if (PlayerInput.KeyHit(Keys.Up)) diff --git a/Subsurface/Source/GameSession/CrewManager.cs b/Subsurface/Source/GameSession/CrewManager.cs index b1b5650e8..3c0c51a56 100644 --- a/Subsurface/Source/GameSession/CrewManager.cs +++ b/Subsurface/Source/GameSession/CrewManager.cs @@ -85,24 +85,28 @@ namespace Barotrauma characterInfos.Add(character.Info); } - GUIFrame frame = new GUIFrame(new Rectangle(0, 0, 0, 40), Color.Transparent, null, listBox); - frame.UserData = character; - frame.Padding = new Vector4(5.0f, 5.0f, 5.0f, 5.0f); - frame.HoverColor = Color.LightGray * 0.5f; - frame.SelectedColor = Color.Gold * 0.5f; + commander.UpdateCharacters(); - string name = character.Info.Name.Replace(' ', '\n'); + character.Info.CreateCharacterFrame(listBox, character.Info.Name.Replace(' ', '\n'), character); - GUITextBlock textBlock = new GUITextBlock( - new Rectangle(40, 0, 0, 25), - name, - Color.Transparent, Color.White, - Alignment.Left, Alignment.Left, - null, frame, false); - textBlock.Font = GUI.SmallFont; - textBlock.Padding = new Vector4(5.0f, 0.0f, 5.0f, 0.0f); + //GUIFrame frame = new GUIFrame(new Rectangle(0, 0, 0, 40), Color.Transparent, null, listBox); + //frame.UserData = character; + //frame.Padding = new Vector4(5.0f, 5.0f, 5.0f, 5.0f); + //frame.HoverColor = Color.LightGray * 0.5f; + //frame.SelectedColor = Color.Gold * 0.5f; - new GUIImage(new Rectangle(-10, -5, 0, 0), character.AnimController.Limbs[0].sprite, Alignment.Left, frame); + //string name = character.Info.Name.Replace(' ', '\n'); + + //GUITextBlock textBlock = new GUITextBlock( + // new Rectangle(40, 0, 0, 25), + // name, + // Color.Transparent, Color.White, + // Alignment.Left, Alignment.Left, + // null, frame, false); + //textBlock.Font = GUI.SmallFont; + //textBlock.Padding = new Vector4(5.0f, 0.0f, 5.0f, 0.0f); + + //new GUIImage(new Rectangle(-10, -5, 0, 0), character.AnimController.Limbs[0].sprite, Alignment.Left, frame); } public void Update(float deltaTime) @@ -123,6 +127,9 @@ namespace Barotrauma GUIComponent characterBlock = listBox.GetChild(killedCharacter) as GUIComponent; if (characterBlock != null) characterBlock.Color = Color.DarkRed * 0.5f; + + commander.UpdateCharacters(); + //if (characters.Find(c => !c.IsDead)==null) //{ // Game1.GameSession.EndShift(null, null); diff --git a/Subsurface/Source/GameSession/HireManager.cs b/Subsurface/Source/GameSession/HireManager.cs index ce3aa1608..60043908b 100644 --- a/Subsurface/Source/GameSession/HireManager.cs +++ b/Subsurface/Source/GameSession/HireManager.cs @@ -12,13 +12,15 @@ namespace Barotrauma { availableCharacters = new List(); } - - public void GenerateCharacters(string file, int amount) - { - + + public void GenerateCharacters(Location location, int amount) + { for (int i = 0 ; i 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; diff --git a/Subsurface/Source/Items/Components/ItemComponent.cs b/Subsurface/Source/Items/Components/ItemComponent.cs index 7f4f750f8..7476bc20c 100644 --- a/Subsurface/Source/Items/Components/ItemComponent.cs +++ b/Subsurface/Source/Items/Components/ItemComponent.cs @@ -38,8 +38,7 @@ namespace Barotrauma.Items.Components /// /// The base class for components holding the different functionalities of the item /// - class - ItemComponent : IPropertyObject + class ItemComponent : IPropertyObject { protected Item item; @@ -400,6 +399,13 @@ namespace Barotrauma.Items.Components /// A vector that can be used to pass additional information to the components public virtual void ItemActivate(Item item, Vector2 modifier) { } + + /// true if the operation was completed + public virtual bool AIOperate(float deltaTime, Character character, AIObjective objective) + { + return false; + } + //called when isActive is true and condition > 0.0f public virtual void Update(float deltaTime, Camera cam) { } diff --git a/Subsurface/Source/Items/Components/ItemContainer.cs b/Subsurface/Source/Items/Components/ItemContainer.cs index 0babebb28..8021ae386 100644 --- a/Subsurface/Source/Items/Components/ItemContainer.cs +++ b/Subsurface/Source/Items/Components/ItemContainer.cs @@ -86,6 +86,11 @@ namespace Barotrauma.Items.Components } private int slotsPerRow; + public List ContainableItems + { + get { return containableItems; } + } + public ItemContainer(Item item, XElement element) : base (item, element) { diff --git a/Subsurface/Source/Items/Components/Machines/Reactor.cs b/Subsurface/Source/Items/Components/Machines/Reactor.cs index 5a4acda62..1f3ee98fa 100644 --- a/Subsurface/Source/Items/Components/Machines/Reactor.cs +++ b/Subsurface/Source/Items/Components/Machines/Reactor.cs @@ -311,12 +311,44 @@ namespace Barotrauma.Items.Components new Vector2(10, 40 * (temperature / 10000.0f)), new Color(temperature / 10000.0f, 1.0f - (temperature / 10000.0f), 0.0f, 1.0f), true); } + public override bool AIOperate(float deltaTime, Character character, AIObjective objective) + { + switch (objective.Option.ToLower()) + { + case "power up": + float tempDiff = load - temperature; - bool valueChanged = false; + shutDownTemp = Math.Min(load + 1000.0f, 7500.0f); + + //temperature too high/low + if (Math.Abs(tempDiff)>500.0f) + { + autoTemp = false; + FissionRate += deltaTime * 100.0f * Math.Sign(tempDiff); + CoolingRate -= deltaTime * 100.0f * Math.Sign(tempDiff); + } + //temperature OK + else + { + autoTemp = true; + } + + break; + case "shutdown": + + shutDownTemp = 0.0f; + + break; + } + + return false; + } + public override void DrawHUD(SpriteBatch spriteBatch, Character character) { IsActive = true; + bool valueChanged = false; int width = GuiFrame.Rect.Width, height = GuiFrame.Rect.Height; int x = GuiFrame.Rect.X; @@ -398,7 +430,6 @@ namespace Barotrauma.Items.Components if (valueChanged) { item.NewComponentEvent(this, true, false); - valueChanged = false; } } diff --git a/Subsurface/Source/Items/Components/Power/PowerContainer.cs b/Subsurface/Source/Items/Components/Power/PowerContainer.cs index 43f78eefc..47612f831 100644 --- a/Subsurface/Source/Items/Components/Power/PowerContainer.cs +++ b/Subsurface/Source/Items/Components/Power/PowerContainer.cs @@ -156,6 +156,13 @@ namespace Barotrauma.Items.Components voltage = 0.0f; } + public override bool AIOperate(float deltaTime, Character character, AIObjective objective) + { + RechargeSpeed = maxRechargeSpeed * 0.5f; + + return true; + } + public override void Draw(SpriteBatch spriteBatch, bool editing) { base.Draw(spriteBatch); diff --git a/Subsurface/Source/Items/Components/Turret.cs b/Subsurface/Source/Items/Components/Turret.cs index 142ce006c..b0a9404cc 100644 --- a/Subsurface/Source/Items/Components/Turret.cs +++ b/Subsurface/Source/Items/Components/Turret.cs @@ -127,67 +127,161 @@ namespace Barotrauma.Items.Components { if (reload > 0.0f) return false; - Projectile projectileComponent = null; - //search for a projectile from linked containers - Item projectile = null; - Item projectileContainer = null; - foreach (MapEntity e in item.linkedTo) - { - projectileContainer = e as Item; - if (projectileContainer == null) continue; - - ItemContainer containerComponent = projectileContainer.GetComponent(); - if (containerComponent == null) continue; - - 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) - { - projectile = containerComponent.inventory.Items[i]; - break; - } - } - - if (projectileComponent != null) break; - } - - if (projectile == null || projectileComponent == null) return false; + var projectiles = GetLoadedProjectiles(true); + if (projectiles.Count == 0) return false; + if (GetAvailablePower() < currPowerConsumption) return false; + + var batteries = item.GetConnectedComponents(); float availablePower = 0.0f; - //List batteries = new List(); - foreach (Connection c in item.Connections) + foreach (PowerContainer battery in batteries) { - foreach (Connection c2 in c.Recipients) - { - if (c2 == null || c2.Item == null) continue; + float batteryPower = Math.Min(battery.Charge, battery.MaxOutPut); + float takePower = Math.Min(currPowerConsumption - availablePower, batteryPower); - PowerContainer batteryComponent = c2.Item.GetComponent(); - if (batteryComponent == null) continue; - - float batteryPower = Math.Min(batteryComponent.Charge, batteryComponent.MaxOutPut); - float takePower = Math.Min(currPowerConsumption - availablePower, batteryPower); - - batteryComponent.Charge -= takePower; - availablePower += takePower; - } + battery.Charge -= takePower; } - reload = reloadTime; - - if (availablePower < currPowerConsumption) return false; - + reload = reloadTime; + + Item projectile = projectiles[0].Item; + projectile.body.ResetDynamics(); projectile.body.Enabled = true; projectile.SetTransform(ConvertUnits.ToSimUnits(new Vector2(item.Rect.X + barrelPos.X, item.Rect.Y - barrelPos.Y)), -rotation); - projectileComponent.Use(deltaTime); - projectileContainer.RemoveContained(projectile); + projectiles[0].Use(deltaTime); + if (projectile.container != null) projectile.container.RemoveContained(projectile); return true; } + public override bool AIOperate(float deltaTime, Character character, AIObjective objective) + { + var projectiles = GetLoadedProjectiles(); + + if (projectiles.Count==0 || (projectiles.Count==1 && objective.Option.ToLower()=="hold fire")) + { + ItemContainer container = null; + foreach (MapEntity e in item.linkedTo) + { + var containerItem = e as Item; + if (containerItem == null) continue; + + container = containerItem.GetComponent(); + if (container != null) break; + } + + if (container == null || container.ContainableItems.Count==0) return true; + + objective.AddSubObjective(new AIObjectiveContainItem(character, container.ContainableItems[0].Names[0], container)); + return false; + } + else if (GetAvailablePower() < powerConsumption) + { + var batteries = item.GetConnectedComponents(); + + float lowestCharge = 0.0f; + PowerContainer batteryToLoad = null; + foreach (PowerContainer battery in batteries) + { + if (batteryToLoad==null || battery.Charge < lowestCharge) + { + batteryToLoad = battery; + lowestCharge = battery.Charge; + } + } + + if (batteryToLoad == null) return true; + + if (batteryToLoad.RechargeSpeed < batteryToLoad.MaxRechargeSpeed*0.4f) + { + objective.AddSubObjective(new AIObjectiveOperateItem(batteryToLoad, character, "")); + return false; + } + + + } + + //enough shells and power + + Character closestEnemy = null; + float closestDist = 3000.0f; + foreach (Character enemy in Character.CharacterList) + { + //ignore humans and characters that are inside the sub + if (enemy.IsDead || enemy.SpeciesName == "human" || enemy.AnimController.CurrentHull != null) continue; + + float dist = Vector2.Distance(enemy.Position, item.Position); + if (dist < closestDist) + { + closestEnemy = enemy; + closestDist = dist; + } + } + + if (closestEnemy == null) return false; + + character.CursorPosition = closestEnemy.Position; + SecondaryUse(deltaTime, character); + + float enemyAngle = MathUtils.VectorToAngle(closestEnemy.Position-item.Position); + float turretAngle = -(rotation - MathHelper.TwoPi); + + if (Math.Abs(enemyAngle - turretAngle) > 0.01f) return false; + + var pickedBody = Submarine.PickBody(item.SimPosition, closestEnemy.SimPosition, null); + if (pickedBody != null && pickedBody.UserData as Limb == null) return false; + + Use(deltaTime, character); + + + return false; + + } + + private float GetAvailablePower() + { + var batteries = item.GetConnectedComponents(); + + float availablePower = 0.0f; + foreach (PowerContainer battery in batteries) + { + float batteryPower = Math.Min(battery.Charge, battery.MaxOutPut); + + availablePower += batteryPower; + } + + return availablePower; + } + + private List GetLoadedProjectiles(bool returnFirst = false) + { + List projectiles = new List(); + + foreach (MapEntity e in item.linkedTo) + { + var projectileContainer = e as Item; + if (projectileContainer == null) continue; + + var containedItems = projectileContainer.ContainedItems; + if (containedItems == null) continue; + + for (int i = 0; i < containedItems.Length; i++) + { + var projectileComponent = containedItems[i].GetComponent(); + if (projectileComponent != null) + { + projectiles.Add(projectileComponent); + if (returnFirst) return projectiles; + } + } + } + + return projectiles; + } + public override void ReceiveSignal(string signal, Connection connection, Item sender, float power) { switch (connection.Name) diff --git a/Subsurface/Source/Items/Item.cs b/Subsurface/Source/Items/Item.cs index 7609969bc..8f4177483 100644 --- a/Subsurface/Source/Items/Item.cs +++ b/Subsurface/Source/Items/Item.cs @@ -681,7 +681,7 @@ namespace Barotrauma private GUIComponent CreateEditingHUD(bool inGame=false) { - int width = 500; + int width = 400; int x = GameMain.GraphicsWidth/2-width/2, y = 10; List editableProperties = inGame ? GetProperties() : GetProperties(); @@ -786,6 +786,26 @@ namespace Barotrauma } } + public List GetConnectedComponents() + { + ConnectionPanel connectionPanel = GetComponent(); + if (connectionPanel == null) return new List(); + + List connectedComponents = new List(); + + foreach (Connection c in connectionPanel.Connections) + { + var recipients = c.Recipients; + foreach (Connection recipient in recipients) + { + var component = recipient.Item.GetComponent(); + if (component != null) connectedComponents.Add(component); + } + } + + return connectedComponents; + } + public void SendSignal(string signal, string connectionName, float power = 0.0f) { ConnectionPanel panel = GetComponent(); @@ -862,6 +882,18 @@ namespace Barotrauma return closest; } + public bool IsInsideTrigger(Vector2 position) + { + foreach (Rectangle trigger in prefab.Triggers) + { + Rectangle transformedTrigger = TransformTrigger(trigger); + + if (Submarine.RectContains(transformedTrigger, position)) return true; + } + + return false; + } + public bool Pick(Character picker, bool ignoreRequiredItems=false, bool forceSelectKey=false, bool forceActionKey=false) { diff --git a/Subsurface/Source/Map/FireSource.cs b/Subsurface/Source/Map/FireSource.cs index 8785da854..41dfc3d87 100644 --- a/Subsurface/Source/Map/FireSource.cs +++ b/Subsurface/Source/Map/FireSource.cs @@ -151,13 +151,17 @@ namespace Barotrauma if (size.X < 100.0f) continue; - var smokeParticle = GameMain.ParticleManager.CreateParticle("smoke", + if (Rand.Int(5) == 1) + { + var smokeParticle = GameMain.ParticleManager.CreateParticle("smoke", spawnPos, speed, 0.0f, hull); - if (smokeParticle != null) - { - smokeParticle.Size *= MathHelper.Clamp(size.X / 100.0f * Math.Max(hull.Oxygen / hull.FullVolume, 0.4f), 0.5f, 4.0f); + if (smokeParticle != null) + { + smokeParticle.Size *= MathHelper.Clamp(size.X / 100.0f * Math.Max(hull.Oxygen / hull.FullVolume, 0.4f), 0.5f, 4.0f); + } } + } DamageCharacters(deltaTime); @@ -166,7 +170,7 @@ namespace Barotrauma if (hull.Volume > 0.0f) HullWaterExtinquish(deltaTime); lightSource.Range = Math.Max(size.X, size.Y) * Rand.Range(8.0f, 10.0f)/2.0f; - lightSource.Color = new Color(1.0f, 0.9f, 0.6f) * Rand.Range(0.8f, 1.0f); + lightSource.Color = new Color(1.0f, 0.45f, 0.3f) * Rand.Range(0.8f, 1.0f); hull.Oxygen -= size.X*deltaTime*OxygenConsumption; diff --git a/Subsurface/Source/Map/Location.cs b/Subsurface/Source/Map/Location.cs index 7e5e067b6..f12e51c4f 100644 --- a/Subsurface/Source/Map/Location.cs +++ b/Subsurface/Source/Map/Location.cs @@ -52,7 +52,7 @@ namespace Barotrauma if (type.HasHireableCharacters) { hireManager = new HireManager(); - hireManager.GenerateCharacters(Character.HumanConfigFile, 10); + hireManager.GenerateCharacters(this, 10); } Connections = new List(); diff --git a/Subsurface/Source/Map/LocationType.cs b/Subsurface/Source/Map/LocationType.cs index 64f94b397..a75c36dc0 100644 --- a/Subsurface/Source/Map/LocationType.cs +++ b/Subsurface/Source/Map/LocationType.cs @@ -24,11 +24,9 @@ namespace Barotrauma private Sprite backGround; - public bool HasHireableCharacters - { - get; - private set; - } + // + private List> hireableJobs; + private float totalHireableWeight; public string Name { @@ -40,6 +38,11 @@ namespace Barotrauma get { return nameFormats; } } + public bool HasHireableCharacters + { + get { return hireableJobs.Any(); } + } + public Sprite Sprite { get { return symbolSprite; } @@ -57,21 +60,51 @@ namespace Barotrauma commonness = ToolBox.GetAttributeInt(element, "commonness", 1); totalWeight += commonness; - HasHireableCharacters = ToolBox.GetAttributeBool(element, "hireablecharacters", false); - nameFormats = new List(); foreach (XAttribute nameFormat in element.Element("nameformats").Attributes()) { nameFormats.Add(nameFormat.Value); } + hireableJobs = new List>(); + foreach (XElement subElement in element.Elements()) + { + if (subElement.Name.ToString().ToLower() != "hireable") continue; + + string jobName = ToolBox.GetAttributeString(subElement, "name", ""); + + JobPrefab jobPrefab = JobPrefab.List.Find(jp => jp.Name.ToLower() == jobName.ToLower()); + if (jobPrefab==null) + { + DebugConsole.ThrowError("Invalid job name ("+jobName+") in location type "+name); + } + + float jobCommonness = ToolBox.GetAttributeFloat(subElement, "commonness", 1.0f); + totalHireableWeight += jobCommonness; + + Tuple hireableJob = new Tuple(jobPrefab, jobCommonness); + + hireableJobs.Add(hireableJob); + } + string spritePath = ToolBox.GetAttributeString(element, "symbol", "Content/Map/beaconSymbol.png"); symbolSprite = new Sprite(spritePath, new Vector2(0.5f, 0.5f)); string backgroundPath = ToolBox.GetAttributeString(element, "background", ""); backGround = new Sprite(backgroundPath, Vector2.Zero); - //sprite.Origin = ; + } + public JobPrefab GetRandomHireable() + { + float randFloat = Rand.Range(0.0f, totalHireableWeight); + + foreach (Tuple hireable in hireableJobs) + { + if (randFloat < hireable.Item2) return hireable.Item1; + randFloat -= hireable.Item2; + } + + return null; } public static LocationType Random() diff --git a/Subsurface/Source/Networking/GameServerSettings.cs b/Subsurface/Source/Networking/GameServerSettings.cs index 7c5b05e3b..ee30ec613 100644 --- a/Subsurface/Source/Networking/GameServerSettings.cs +++ b/Subsurface/Source/Networking/GameServerSettings.cs @@ -85,7 +85,7 @@ namespace Barotrauma.Networking var selectionFrame = new GUIFrame(new Rectangle(0, 60, 300, 20), null, innerFrame); for (int i = 0; i<3; i++) { - var selectionTick = new GUITickBox(new Rectangle(i * 100, 00, 20, 20), ((SelectionMode)i).ToString(), Alignment.Left, selectionFrame); + var selectionTick = new GUITickBox(new Rectangle(i * 100, 0, 20, 20), ((SelectionMode)i).ToString(), Alignment.Left, selectionFrame); selectionTick.Selected = i == (int)subSelectionMode; selectionTick.OnSelected = SwitchSubSelection; selectionTick.UserData = (SelectionMode)i; @@ -100,14 +100,11 @@ namespace Barotrauma.Networking selectionTick.OnSelected = SwitchModeSelection; selectionTick.UserData = (SelectionMode)i; } - - - var allowSpecBox = new GUITickBox(new Rectangle(0, 0, 20, 20), "Allow spectating", Alignment.Left, innerFrame); - allowSpecBox.Selected = true; - allowSpecBox.OnSelected = ToggleAllowSpectating; - - + var allowSpecBox = new GUITickBox(new Rectangle(0, 150, 20, 20), "Allow spectating", Alignment.Left, innerFrame); + allowSpecBox.Selected = true; + allowSpecBox.OnSelected = ToggleAllowSpectating; + var closeButton = new GUIButton(new Rectangle(0, 0, 100, 20), "Close", Alignment.BottomRight, GUI.Style, innerFrame); closeButton.OnClicked = ToggleSettingsFrame; } diff --git a/Subsurface/Source/Screens/LobbyScreen.cs b/Subsurface/Source/Screens/LobbyScreen.cs index efe223844..d1f02bf5d 100644 --- a/Subsurface/Source/Screens/LobbyScreen.cs +++ b/Subsurface/Source/Screens/LobbyScreen.cs @@ -144,12 +144,12 @@ namespace Barotrauma itemList = new GUIListBox(new Rectangle(0, 0, sellColumnWidth, 400), Color.White * 0.7f, Alignment.TopRight, GUI.Style, bottomPanel[(int)PanelTab.Store]); itemList.OnSelected = SelectItem; - foreach (MapEntityPrefab ep in MapEntityPrefab.list) - { - if (ep.Price == 0) continue; + foreach (MapEntityPrefab ep in MapEntityPrefab.list) + { + if (ep.Price == 0) continue; - CreateItemFrame(ep, itemList); - } + CreateItemFrame(ep, itemList); + } } public override void Select() @@ -158,7 +158,16 @@ namespace Barotrauma gameMode = GameMain.GameSession.gameMode as SinglePlayerMode; - //Map.Unload(); + foreach (GUIComponent component in topPanel.children) + { + var button = component as GUIButton; + if (button == null || button.Text != "Hire") continue; + + button.Enabled = GameMain.GameSession.Map.CurrentLocation.Type.HasHireableCharacters; + break; + } + //hireButton.Enabled = location.Type.HasHireableCharacters; + UpdateCharacterLists(); } @@ -173,6 +182,7 @@ namespace Barotrauma locationTitle.Font = GUI.LargeFont; bottomPanel[(int)PanelTab.CurrentLocation].ClearChildren(); + bottomPanel[(int)PanelTab.CurrentLocation].UserData = location; //rightPanel[(int)PanelTab.Hire].Padding = GUI.style.smallPadding; //for (int i = 0; i < Enum.GetNames(typeof(PanelTab)).Length; i++ ) @@ -208,16 +218,18 @@ namespace Barotrauma hireList.ClearChildren(); foreach (CharacterInfo c in location.HireManager.availableCharacters) { - GUITextBlock textBlock = new GUITextBlock( - new Rectangle(0, 0, 0, 25), - c.Name + " (" + c.Job.Name + ")", GUI.Style, hireList); - textBlock.UserData = c; + var frame = c.CreateCharacterFrame(hireList, c.Name + " (" + c.Job.Name + ")", c); - textBlock = new GUITextBlock( + //GUITextBlock textBlock = new GUITextBlock( + // new Rectangle(0, 0, 0, 25), + // c.Name + " (" + c.Job.Name + ")", GUI.Style, hireList); + //textBlock.UserData = c; + + var textBlock = new GUITextBlock( new Rectangle(0, 0, 0, 25), c.Salary.ToString(), null, null, - Alignment.TopRight, GUI.Style, textBlock); + Alignment.TopRight, GUI.Style, frame); } } else @@ -240,22 +252,22 @@ namespace Barotrauma if (locationPanel != null) bottomPanel[(int)PanelTab.Map].RemoveChild(locationPanel); - locationPanel = new GUIFrame(new Rectangle(0, 0, 200, 190), Color.Transparent, Alignment.TopRight, null, bottomPanel[(int)PanelTab.Map]); + locationPanel = new GUIFrame(new Rectangle(0, 0, 250, 190), Color.Transparent, Alignment.TopRight, null, bottomPanel[(int)PanelTab.Map]); locationPanel.UserData = "selectedlocation"; if (location == null) return; - new GUITextBlock(new Rectangle(0,0,0,0), location.Name, Color.Transparent, Color.White, Alignment.TopLeft, null, locationPanel); + new GUITextBlock(new Rectangle(0, 0, 0, 0), location.Name, Color.Black * 0.8f, Color.White, Alignment.TopLeft, null, locationPanel).Font = GUI.LargeFont; if (GameMain.GameSession.Map.SelectedConnection != null && GameMain.GameSession.Map.SelectedConnection.Quest != null) { var quest = GameMain.GameSession.Map.SelectedConnection.Quest; - new GUITextBlock(new Rectangle(0, 40, 0, 20), "Quest: "+quest.Name, Color.Transparent, Color.White, Alignment.TopLeft, null, locationPanel); - - new GUITextBlock(new Rectangle(0, 60, 0, 20), "Reward: " + quest.Reward, Color.Transparent, Color.White, Alignment.TopLeft, null, locationPanel); - - new GUITextBlock(new Rectangle(0, 80, 0, 0), quest.Description, Color.Transparent, Color.White, Alignment.TopLeft, null, locationPanel, true); + new GUITextBlock(new Rectangle(0, 40, 0, 20), "Quest: "+quest.Name, Color.Black*0.8f, Color.White, Alignment.TopLeft, null, locationPanel); + + new GUITextBlock(new Rectangle(0, 60, 0, 20), "Reward: " + quest.Reward, Color.Black * 0.8f, Color.White, Alignment.TopLeft, null, locationPanel); + + new GUITextBlock(new Rectangle(0, 80, 0, 0), quest.Description, Color.Black * 0.8f, Color.White, Alignment.TopLeft, null, locationPanel, true); } @@ -269,14 +281,16 @@ namespace Barotrauma characterList.ClearChildren(); foreach (CharacterInfo c in CrewManager.characterInfos) { - GUITextBlock textBlock = new GUITextBlock( - new Rectangle(0, 0, 0, 25), - c.Name + " (" + c.Job.Name + ")", GUI.Style, - Alignment.Left, - Alignment.Left, - characterList, false, GameMain.GraphicsWidth<1000 ? GUI.SmallFont : GUI.Font); - textBlock.Padding = new Vector4(10.0f, 0.0f, 0.0f, 0.0f); - textBlock.UserData = c; + c.CreateCharacterFrame(characterList, c.Name + " ("+c.Job.Name+") ", c); + + //GUITextBlock textBlock = new GUITextBlock( + // new Rectangle(0, 0, 0, 25), + // c.Name + " (" + c.Job.Name + ")", GUI.Style, + // Alignment.Left, + // Alignment.Left, + // characterList, false, GameMain.GraphicsWidth<1000 ? GUI.SmallFont : GUI.Font); + //textBlock.Padding = new Vector4(10.0f, 0.0f, 0.0f, 0.0f); + //textBlock.UserData = c; } } @@ -403,7 +417,7 @@ namespace Barotrauma GameMain.GameSession.Map.Draw(spriteBatch, new Rectangle( bottomPanel[selectedRightPanel].Rect.X + 20, bottomPanel[selectedRightPanel].Rect.Y + 20, - bottomPanel[selectedRightPanel].Rect.Width - 280, + bottomPanel[selectedRightPanel].Rect.Width - 310, bottomPanel[selectedRightPanel].Rect.Height - 40), mapZoom); } @@ -449,6 +463,16 @@ namespace Barotrauma private bool SelectCharacter(GUIComponent component, object selection) { + GUIComponent prevInfoFrame = null; + foreach (GUIComponent child in bottomPanel[selectedRightPanel].children) + { + if (child.UserData as CharacterInfo == null) continue; + + prevInfoFrame = child; + } + + if (prevInfoFrame != null) bottomPanel[selectedRightPanel].RemoveChild(prevInfoFrame); + CharacterInfo characterInfo = selection as CharacterInfo; if (characterInfo == null) return false; diff --git a/Subsurface_Solution.v12.suo b/Subsurface_Solution.v12.suo index 30a66e032..2a5250160 100644 Binary files a/Subsurface_Solution.v12.suo and b/Subsurface_Solution.v12.suo differ