diff --git a/Barotrauma/BarotraumaClient/Source/Items/Components/Door.cs b/Barotrauma/BarotraumaClient/Source/Items/Components/Door.cs index 193ce722a..90c3e8bbc 100644 --- a/Barotrauma/BarotraumaClient/Source/Items/Components/Door.cs +++ b/Barotrauma/BarotraumaClient/Source/Items/Components/Door.cs @@ -87,11 +87,7 @@ namespace Barotrauma.Items.Components public void Draw(SpriteBatch spriteBatch, bool editing) { Color color = (item.IsSelected) ? Color.Green : Color.White; - color = color * (item.Condition / item.Prefab.Health); - color.A = 255; - - //prefab.sprite.Draw(spriteBatch, new Vector2(rect.X, -rect.Y), new Vector2(rect.Width, rect.Height), color); - + if (stuck > 0.0f && weldedSprite != null) { Vector2 weldSpritePos = new Vector2(item.Rect.Center.X, item.Rect.Y - item.Rect.Height / 2.0f); @@ -114,10 +110,25 @@ namespace Barotrauma.Items.Components if (item.Submarine != null) pos += item.Submarine.DrawPosition; pos.Y = -pos.Y; - spriteBatch.Draw(doorSprite.Texture, pos, - new Rectangle((int)(doorSprite.SourceRect.X + doorSprite.size.X * openState), (int)doorSprite.SourceRect.Y, - (int)(doorSprite.size.X * (1.0f - openState)), (int)doorSprite.size.Y), - color, 0.0f, doorSprite.Origin, 1.0f, SpriteEffects.None, doorSprite.Depth); + if (brokenSprite == null || item.Health > 0.0f) + { + spriteBatch.Draw(doorSprite.Texture, pos, + new Rectangle((int) (doorSprite.SourceRect.X + doorSprite.size.X * openState), + (int) doorSprite.SourceRect.Y, + (int) (doorSprite.size.X * (1.0f - openState)), (int) doorSprite.size.Y), + color, 0.0f, doorSprite.Origin, 1.0f, SpriteEffects.None, doorSprite.Depth); + } + + if (brokenSprite != null && item.Health < item.Prefab.Health) + { + Vector2 scale = scaleBrokenSprite ? new Vector2(1.0f, 1.0f - item.Health / item.Prefab.Health) : Vector2.One; + float alpha = fadeBrokenSprite ? 1.0f - item.Health / item.Prefab.Health : 1.0f; + spriteBatch.Draw(brokenSprite.Texture, pos, + new Rectangle((int)(brokenSprite.SourceRect.X + brokenSprite.size.X * openState), brokenSprite.SourceRect.Y, + (int)(brokenSprite.size.X * (1.0f - openState)), (int)brokenSprite.size.Y), + color * alpha, 0.0f, brokenSprite.Origin, scale, SpriteEffects.None, + brokenSprite.Depth); + } } else { @@ -125,10 +136,25 @@ namespace Barotrauma.Items.Components if (item.Submarine != null) pos += item.Submarine.DrawPosition; pos.Y = -pos.Y; - spriteBatch.Draw(doorSprite.Texture, pos, - new Rectangle(doorSprite.SourceRect.X, (int)(doorSprite.SourceRect.Y + 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 (brokenSprite == null || item.Health > 0.0f) + { + spriteBatch.Draw(doorSprite.Texture, pos, + new Rectangle(doorSprite.SourceRect.X, + (int) (doorSprite.SourceRect.Y + 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 (brokenSprite != null && item.Health < item.Prefab.Health) + { + Vector2 scale = scaleBrokenSprite ? new Vector2(1.0f - item.Health / item.Prefab.Health, 1.0f) : Vector2.One; + float alpha = fadeBrokenSprite ? 1.0f - item.Health / item.Prefab.Health : 1.0f; + spriteBatch.Draw(brokenSprite.Texture, pos, + new Rectangle(brokenSprite.SourceRect.X, (int)(brokenSprite.SourceRect.Y + brokenSprite.size.Y * openState), + (int)brokenSprite.size.X, (int)(brokenSprite.size.Y * (1.0f - openState))), + color * alpha, 0.0f, brokenSprite.Origin, scale, SpriteEffects.None, brokenSprite.Depth); + } + } } diff --git a/Barotrauma/BarotraumaShared/BarotraumaShared.projitems b/Barotrauma/BarotraumaShared/BarotraumaShared.projitems index 2691ec529..8f03bf746 100644 --- a/Barotrauma/BarotraumaShared/BarotraumaShared.projitems +++ b/Barotrauma/BarotraumaShared/BarotraumaShared.projitems @@ -289,6 +289,9 @@ PreserveNewest + + PreserveNewest + PreserveNewest diff --git a/Barotrauma/BarotraumaShared/Content/Items/Door/door.png b/Barotrauma/BarotraumaShared/Content/Items/Door/door.png index 435e2a5bf..2b15f795a 100644 Binary files a/Barotrauma/BarotraumaShared/Content/Items/Door/door.png and b/Barotrauma/BarotraumaShared/Content/Items/Door/door.png differ diff --git a/Barotrauma/BarotraumaShared/Content/Items/Door/doors.xml b/Barotrauma/BarotraumaShared/Content/Items/Door/doors.xml index a90974cfa..120365d6c 100644 --- a/Barotrauma/BarotraumaShared/Content/Items/Door/doors.xml +++ b/Barotrauma/BarotraumaShared/Content/Items/Door/doors.xml @@ -9,6 +9,7 @@ + @@ -32,11 +33,12 @@ linkable="true" > - + - - + + + @@ -60,11 +62,12 @@ linkable="true" > - + - - + + + diff --git a/Barotrauma/BarotraumaShared/Content/Items/Door/hatch.png b/Barotrauma/BarotraumaShared/Content/Items/Door/hatch.png new file mode 100644 index 000000000..73fa437cc Binary files /dev/null and b/Barotrauma/BarotraumaShared/Content/Items/Door/hatch.png differ diff --git a/Barotrauma/BarotraumaShared/Source/Items/Components/Door.cs b/Barotrauma/BarotraumaShared/Source/Items/Components/Door.cs index 7d3123786..eb68e1949 100644 --- a/Barotrauma/BarotraumaShared/Source/Items/Components/Door.cs +++ b/Barotrauma/BarotraumaShared/Source/Items/Components/Door.cs @@ -25,7 +25,8 @@ namespace Barotrauma.Items.Components private PhysicsBody body; - private Sprite doorSprite, weldedSprite; + private Sprite doorSprite, weldedSprite, brokenSprite; + private bool scaleBrokenSprite, fadeBrokenSprite; private bool isHorizontal; @@ -34,6 +35,28 @@ namespace Barotrauma.Items.Components private bool? predictedState; private float resetPredictionTimer; + private Rectangle doorRect; + + private bool isBroken; + + public bool IsBroken + { + get { return isBroken; } + set + { + if (isBroken == value) return; + isBroken = value; + if (isBroken) + { + DisableBody(); + } + else + { + EnableBody(); + } + } + } + public PhysicsBody Body { get { return body; } @@ -45,7 +68,7 @@ namespace Barotrauma.Items.Components get { return stuck; } set { - if (isOpen) return; + if (isOpen || isBroken) return; stuck = MathHelper.Clamp(value, 0.0f, 100.0f); if (stuck == 0.0f) isStuck = false; if (stuck == 100.0f) isStuck = true; @@ -117,8 +140,6 @@ namespace Barotrauma.Items.Components OpenState = (isOpen) ? 1.0f : 0.0f; } } - - private Rectangle doorRect; public float OpenState { @@ -139,11 +160,8 @@ namespace Barotrauma.Items.Components public Door(Item item, XElement element) : base(item, element) { - //Vector2 position = new Vector2(newRect.X, newRect.Y); - isHorizontal = element.GetAttributeBool("horizontal", false); - - // isOpen = false; + foreach (XElement subElement in element.Elements()) { string texturePath = subElement.GetAttributeString("texture", ""); @@ -155,6 +173,11 @@ namespace Barotrauma.Items.Components case "weldedsprite": weldedSprite = new Sprite(subElement, texturePath.Contains("/") ? "" : Path.GetDirectoryName(item.Prefab.ConfigFile)); break; + case "brokensprite": + brokenSprite = new Sprite(subElement, texturePath.Contains("/") ? "" : Path.GetDirectoryName(item.Prefab.ConfigFile)); + scaleBrokenSprite = subElement.GetAttributeBool("scale", false); + fadeBrokenSprite = subElement.GetAttributeBool("fade", false); + break; } } @@ -177,9 +200,6 @@ namespace Barotrauma.Items.Components ConvertUnits.ToSimUnits(new Vector2(doorRect.Center.X, doorRect.Y - doorRect.Height / 2)), 0.0f); body.Friction = 0.5f; - - - //string spritePath = Path.GetDirectoryName(item.Prefab.ConfigFile) + "\\"+ ToolBox.GetAttributeString(element, "sprite", ""); IsActive = true; } @@ -187,17 +207,12 @@ namespace Barotrauma.Items.Components public override void Move(Vector2 amount) { base.Move(amount); - - //LinkedGap.Move(amount); - + body.SetTransform(body.SimPosition + ConvertUnits.ToSimUnits(amount), 0.0f); #if CLIENT UpdateConvexHulls(); #endif - - //convexHull.Move(amount); - //if (convexHull2 != null) convexHull2.Move(amount); } @@ -216,17 +231,27 @@ namespace Barotrauma.Items.Components public override void Update(float deltaTime, Camera cam) { + if (isBroken) + { + //the door has to be restored to 50% health before collision detection on the body is re-enabled + if (item.Condition > 50.0f) + { + IsBroken = false; + } + return; + } + bool isClosing = false; if (!isStuck) { if (predictedState == null) { - OpenState += deltaTime * ((isOpen) ? 2.0f : -2.0f); + OpenState += deltaTime * (isOpen ? 2.0f : -2.0f); isClosing = openState > 0.0f && openState < 1.0f && !isOpen; } else { - OpenState += deltaTime * (((bool)predictedState) ? 2.0f : -2.0f); + OpenState += deltaTime * ((bool)predictedState ? 2.0f : -2.0f); isClosing = openState > 0.0f && openState < 1.0f && !(bool)predictedState; resetPredictionTimer -= deltaTime; @@ -252,14 +277,34 @@ namespace Barotrauma.Items.Components //other items to an incorrect state if the prediction is wrong item.SendSignal(0, (isOpen) ? "1" : "0", "state_out", null); } - + public override void UpdateBroken(float deltaTime, Camera cam) { - body.Enabled = false; - - linkedGap.Open = 1.0f; + IsBroken = true; } - + + private void EnableBody() + { + body.FarseerBody.IsSensor = false; +#if CLIENT + UpdateConvexHulls(); +#endif + isBroken = false; + } + + private void DisableBody() + { + //change the body to a sensor instead of disabling it completely, + //because otherwise repairtool raycasts won't hit it + body.FarseerBody.IsSensor = true; + linkedGap.Open = 1.0f; + IsOpen = false; +#if CLIENT + if (convexHull != null) convexHull.Enabled = false; + if (convexHull2 != null) convexHull2.Enabled = false; +#endif + } + public override void OnMapLoaded() { LinkedGap.ConnectedDoor = this; @@ -280,19 +325,19 @@ namespace Barotrauma.Items.Components base.RemoveComponentSpecific(); if (body != null) - { + { body.Remove(); body = null; } - if (linkedGap!=null) linkedGap.Remove(); + if (linkedGap != null) linkedGap.Remove(); doorSprite.Remove(); if (weldedSprite != null) weldedSprite.Remove(); #if CLIENT - if (convexHull!=null) convexHull.Remove(); + if (convexHull != null) convexHull.Remove(); if (convexHull2 != null) convexHull2.Remove(); #endif } @@ -398,8 +443,8 @@ namespace Barotrauma.Items.Components { //clients can "predict" that the door opens/closes when a signal is received -//the prediction will be reset after 1 second, setting the door to a state -//sent by the server, or reverting it back to its old state if no msg from server was received + //the prediction will be reset after 1 second, setting the door to a state + //sent by the server, or reverting it back to its old state if no msg from server was received #if CLIENT if (open != predictedState) PlaySound(ActionType.OnUse, item.WorldPosition); @@ -437,7 +482,7 @@ namespace Barotrauma.Items.Components { SetState(msg.ReadBoolean(), true); Stuck = msg.ReadRangedSingle(0.0f, 100.0f, 8); - + predictedState = null; } } diff --git a/Barotrauma/BarotraumaShared/Source/Items/Components/Holdable/RepairTool.cs b/Barotrauma/BarotraumaShared/Source/Items/Components/Holdable/RepairTool.cs index f80b113ab..4d385c36d 100644 --- a/Barotrauma/BarotraumaShared/Source/Items/Components/Holdable/RepairTool.cs +++ b/Barotrauma/BarotraumaShared/Source/Items/Components/Holdable/RepairTool.cs @@ -176,7 +176,7 @@ namespace Barotrauma.Items.Components } Body targetBody = Submarine.PickBody(rayStart, rayEnd, ignoredBodies, - Physics.CollisionWall | Physics.CollisionCharacter | Physics.CollisionItem | Physics.CollisionLevel); + Physics.CollisionWall | Physics.CollisionCharacter | Physics.CollisionItem | Physics.CollisionLevel, false); if (targetBody == null || targetBody.UserData == null) return; diff --git a/Barotrauma/BarotraumaShared/Source/Map/Submarine.cs b/Barotrauma/BarotraumaShared/Source/Map/Submarine.cs index dd5318715..fb36727a2 100644 --- a/Barotrauma/BarotraumaShared/Source/Map/Submarine.cs +++ b/Barotrauma/BarotraumaShared/Source/Map/Submarine.cs @@ -509,7 +509,7 @@ namespace Barotrauma } } - public static Body PickBody(Vector2 rayStart, Vector2 rayEnd, List ignoredBodies = null, Category? collisionCategory = null) + public static Body PickBody(Vector2 rayStart, Vector2 rayEnd, List ignoredBodies = null, Category? collisionCategory = null, bool ignoreSensors = true) { if (Vector2.DistanceSquared(rayStart, rayEnd) < 0.00001f) { @@ -521,7 +521,7 @@ namespace Barotrauma GameMain.World.RayCast((fixture, point, normal, fraction) => { if (fixture == null || - fixture.IsSensor || + (ignoreSensors && fixture.IsSensor) || fixture.CollisionCategories == Category.None || fixture.CollisionCategories == Physics.CollisionItem) return -1; @@ -556,7 +556,7 @@ namespace Barotrauma /// check visibility between two points (in sim units) /// /// a physics body that was between the points (or null) - public static Body CheckVisibility(Vector2 rayStart, Vector2 rayEnd, bool ignoreLevel = false, bool ignoreSubs = false) + public static Body CheckVisibility(Vector2 rayStart, Vector2 rayEnd, bool ignoreLevel = false, bool ignoreSubs = false, bool ignoreSensors = true) { Body closestBody = null; float closestFraction = 1.0f; @@ -569,7 +569,8 @@ namespace Barotrauma GameMain.World.RayCast((fixture, point, normal, fraction) => { - if (fixture == null || fixture.IsSensor || + if (fixture == null || + (ignoreSensors && fixture.IsSensor) || (!fixture.CollisionCategories.HasFlag(Physics.CollisionWall) && !fixture.CollisionCategories.HasFlag(Physics.CollisionLevel))) return -1; if (ignoreLevel && fixture.CollisionCategories == Physics.CollisionLevel) return -1;