diff --git a/Barotrauma/BarotraumaClient/Source/Characters/Animation/Ragdoll.cs b/Barotrauma/BarotraumaClient/Source/Characters/Animation/Ragdoll.cs index 17f75eb98..fa8066d54 100644 --- a/Barotrauma/BarotraumaClient/Source/Characters/Animation/Ragdoll.cs +++ b/Barotrauma/BarotraumaClient/Source/Characters/Animation/Ragdoll.cs @@ -1,4 +1,5 @@ -using FarseerPhysics; +using Barotrauma.Items.Components; +using FarseerPhysics; using FarseerPhysics.Dynamics; using FarseerPhysics.Dynamics.Joints; using Microsoft.Xna.Framework; @@ -20,7 +21,12 @@ namespace Barotrauma if (impact > 3.0f && limb.HitSound != null && limb.SoundTimer <= 0.0f) { limb.SoundTimer = Limb.SoundInterval; - limb.HitSound.Play(volume, impact * 100.0f, limb.WorldPosition); + SoundPlayer.PlaySound(limb.HitSound, volume, impact * 100.0f, limb.WorldPosition); + foreach(WearableSprite wearable in limb.WearingItems) + { + if (limb.type == wearable.Limb && wearable.Sound != null) + SoundPlayer.PlaySound(wearable.Sound, volume, impact * 100.0f, limb.WorldPosition); + } } } else if (body.UserData is Limb || body == Collider.FarseerBody) @@ -29,7 +35,7 @@ namespace Barotrauma { if (impact > ImpactTolerance) { - SoundPlayer.PlayDamageSound(DamageSoundType.LimbBlunt, strongestImpact, Collider); + SoundPlayer.PlayDamageSound("LimbBlunt", strongestImpact, Collider); } } diff --git a/Barotrauma/BarotraumaClient/Source/Characters/Limb.cs b/Barotrauma/BarotraumaClient/Source/Characters/Limb.cs index d73911a8c..d72a33ec8 100644 --- a/Barotrauma/BarotraumaClient/Source/Characters/Limb.cs +++ b/Barotrauma/BarotraumaClient/Source/Characters/Limb.cs @@ -19,7 +19,7 @@ namespace Barotrauma private Sound hitSound; - public Sound HitSound + public string HitSound { get { return hitSound; } } @@ -34,7 +34,7 @@ namespace Barotrauma LightSource = new LightSource(subElement); break; case "sound": - hitSound = Sound.Load(subElement.GetAttributeString("file", "")); + hitSound = subElement.GetAttributeString("file", ""); break; } } diff --git a/Barotrauma/BarotraumaClient/Source/GameSession/RoundSummary.cs b/Barotrauma/BarotraumaClient/Source/GameSession/RoundSummary.cs index 256b5d0fa..7fbca38ac 100644 --- a/Barotrauma/BarotraumaClient/Source/GameSession/RoundSummary.cs +++ b/Barotrauma/BarotraumaClient/Source/GameSession/RoundSummary.cs @@ -26,7 +26,7 @@ namespace Barotrauma { bool singleplayer = GameMain.NetworkMember == null; - bool gameOver = gameSession.CrewManager.GetCharacters().All(c => c.IsDead); + bool gameOver = gameSession.CrewManager.GetCharacters().All(c => c.IsDead || c.IsUnconscious); bool progress = Submarine.MainSub.AtEndPosition; GUIFrame frame = new GUIFrame(new Rectangle(0, 0, GameMain.GraphicsWidth, GameMain.GraphicsHeight), Color.Black * 0.8f, null); @@ -36,19 +36,23 @@ namespace Barotrauma int y = 0; - if (singleplayer) + if (!singleplayer) { - string summaryText = TextManager.Get(gameOver ? "RoundSummaryGameOver" : - (progress ? "RoundSummaryProgress" : "RoundSummaryReturn")); - - summaryText = summaryText - .Replace("[sub]", Submarine.MainSub.Name) - .Replace("[location]", GameMain.GameSession.StartLocation.Name); - - var infoText = new GUITextBlock(new Rectangle(0, y, 0, 50), summaryText, "", innerFrame, true); - y += infoText.Rect.Height; + //Game over if everyone dead or didn't progress + gameOver = gameOver || !progress; + SoundPlayer.OverrideMusicType = gameOver ? "crewdead" : "endround"; } + string summaryText = TextManager.Get(gameOver ? "RoundSummaryGameOver" : + (progress ? "RoundSummaryProgress" : "RoundSummaryReturn")); + + summaryText = summaryText + .Replace("[sub]", Submarine.MainSub.Name) + .Replace("[location]", GameMain.GameSession.StartLocation.Name); + + var infoText = new GUITextBlock(new Rectangle(0, y, 0, 50), summaryText, "", innerFrame, true); + y += infoText.Rect.Height; + if (!string.IsNullOrWhiteSpace(endMessage)) { var endText = new GUITextBlock(new Rectangle(0, y, 0, 30), endMessage, "", innerFrame, true); diff --git a/Barotrauma/BarotraumaClient/Source/Items/CharacterInventory.cs b/Barotrauma/BarotraumaClient/Source/Items/CharacterInventory.cs index f61478ce4..e6b0c88b6 100644 --- a/Barotrauma/BarotraumaClient/Source/Items/CharacterInventory.cs +++ b/Barotrauma/BarotraumaClient/Source/Items/CharacterInventory.cs @@ -143,6 +143,10 @@ namespace Barotrauma { wasPut = character.SelectedCharacter.Inventory.TryPutItem(doubleClickedItem, Character.Controlled, doubleClickedItem.AllowedSlots, true); } + else if (character.SelectedBy != null && Character.Controlled == character.SelectedBy && character.SelectedBy.Inventory != null) + { + wasPut = character.SelectedBy.Inventory.TryPutItem(doubleClickedItem, Character.Controlled, doubleClickedItem.AllowedSlots, true); + } else //doubleclicked and no other inventory is selected { //not equipped -> attempt to equip diff --git a/Barotrauma/BarotraumaClient/Source/Items/Components/Machines/Fabricator.cs b/Barotrauma/BarotraumaClient/Source/Items/Components/Machines/Fabricator.cs index 63176af8a..fb3aebc16 100644 --- a/Barotrauma/BarotraumaClient/Source/Items/Components/Machines/Fabricator.cs +++ b/Barotrauma/BarotraumaClient/Source/Items/Components/Machines/Fabricator.cs @@ -111,9 +111,9 @@ namespace Barotrauma.Items.Components if (!inadequateSkills.Any()) { text = "Required items:\n"; - foreach (Tuple ip in targetItem.RequiredItems) + foreach (Tuple ip in targetItem.RequiredItems) { - text += " - " + ip.Item1.Name + " x" + ip.Item2 + "\n"; + text += " - " + ip.Item1.Name + " x" + ip.Item2 + (ip.Item3 < 1.0f ? ", " + ip.Item3 * 100 + "% condition\n" : "\n"); } text += "Required time: " + targetItem.RequiredTime + " s"; } diff --git a/Barotrauma/BarotraumaClient/Source/Items/Components/StatusHUD.cs b/Barotrauma/BarotraumaClient/Source/Items/Components/StatusHUD.cs index f887e47c1..8b987f5c5 100644 --- a/Barotrauma/BarotraumaClient/Source/Items/Components/StatusHUD.cs +++ b/Barotrauma/BarotraumaClient/Source/Items/Components/StatusHUD.cs @@ -127,6 +127,7 @@ namespace Barotrauma.Items.Components if (target.IsDead) { texts.Add("Deceased"); + texts.Add("Cause of Death: " + target.CauseOfDeath.ToString()); } else { diff --git a/Barotrauma/BarotraumaClient/Source/Sounds/Sound.cs b/Barotrauma/BarotraumaClient/Source/Sounds/Sound.cs index c1dd80996..34ebeb3d3 100644 --- a/Barotrauma/BarotraumaClient/Source/Sounds/Sound.cs +++ b/Barotrauma/BarotraumaClient/Source/Sounds/Sound.cs @@ -87,6 +87,10 @@ namespace Barotrauma DebugConsole.ThrowError("File \"" + file + "\" not found!"); return null; } + + Sound dupe = Sound.loadedSounds.Find(s => s.filePath == file); + if (dupe != null) + return dupe; return new Sound(file, destroyOnGameEnd); } @@ -100,6 +104,9 @@ namespace Barotrauma { newSound.baseVolume = element.GetAttributeFloat("volume", 1.0f); newSound.range = element.GetAttributeFloat("range", 1000.0f); + Sound dupe = Sound.loadedSounds.Find(s => s.filePath == filePath && s.baseVolume == newSound.baseVolume && s.range == newSound.range); + if (dupe != null) + return dupe; } return newSound; diff --git a/Barotrauma/BarotraumaClient/Source/Sounds/SoundPlayer.cs b/Barotrauma/BarotraumaClient/Source/Sounds/SoundPlayer.cs index 9f7055eae..2b2649893 100644 --- a/Barotrauma/BarotraumaClient/Source/Sounds/SoundPlayer.cs +++ b/Barotrauma/BarotraumaClient/Source/Sounds/SoundPlayer.cs @@ -10,26 +10,19 @@ using System.Xml.Linq; namespace Barotrauma { - public enum DamageSoundType - { - None, - StructureBlunt, StructureSlash, - LimbBlunt, LimbSlash, LimbArmor - } - public struct DamageSound { //the range of inflicted damage where the sound can be played //(10.0f, 30.0f) would be played when the inflicted damage is between 10 and 30 public readonly Vector2 damageRange; - public readonly DamageSoundType damageType; + public readonly string damageType; public readonly Sound sound; public readonly string requiredTag; - public DamageSound(Sound sound, Vector2 damageRange, DamageSoundType damageType, string requiredTag = "") + public DamageSound(Sound sound, Vector2 damageRange, string damageType, string requiredTag = "") { this.sound = sound; this.damageRange = damageRange; @@ -161,8 +154,7 @@ namespace Barotrauma Sound damageSound = Sound.Load(subElement.GetAttributeString("file", ""), false); if (damageSound == null) continue; - DamageSoundType damageSoundType = DamageSoundType.None; - Enum.TryParse(subElement.GetAttributeString("damagesoundtype", "None"), false, out damageSoundType); + string damageSoundType = subElement.GetAttributeString("damagesoundtype", "None"); damageSounds.Add(new DamageSound( damageSound, @@ -271,7 +263,7 @@ namespace Barotrauma public static Sound GetSound(string soundTag) { var matchingSounds = miscSounds[soundTag].ToList(); - if (matchingSounds.Count == 0) return null; + if (matchingSounds.Count == 0) return Sound.Load(soundTag); return matchingSounds[Rand.Int(matchingSounds.Count)]; } @@ -442,14 +434,14 @@ namespace Barotrauma SplashSounds[splashIndex].Play(1.0f, 800.0f, worldPosition); } - public static void PlayDamageSound(DamageSoundType damageType, float damage, PhysicsBody body) + public static void PlayDamageSound(string damageType, float damage, PhysicsBody body) { Vector2 bodyPosition = body.DrawPosition; PlayDamageSound(damageType, damage, bodyPosition, 800.0f); } - public static void PlayDamageSound(DamageSoundType damageType, float damage, Vector2 position, float range = 2000.0f, List tags = null) + public static void PlayDamageSound(string damageType, float damage, Vector2 position, float range = 2000.0f, List tags = null) { damage = MathHelper.Clamp(damage+Rand.Range(-10.0f, 10.0f), 0.0f, 100.0f); var sounds = damageSounds.FindAll(s => diff --git a/Barotrauma/BarotraumaShared/BarotraumaShared.projitems b/Barotrauma/BarotraumaShared/BarotraumaShared.projitems index 6a759c373..99d25522f 100644 --- a/Barotrauma/BarotraumaShared/BarotraumaShared.projitems +++ b/Barotrauma/BarotraumaShared/BarotraumaShared.projitems @@ -295,6 +295,9 @@ PreserveNewest + + PreserveNewest + PreserveNewest @@ -740,7 +743,7 @@ PreserveNewest - Always + PreserveNewest PreserveNewest @@ -925,6 +928,9 @@ PreserveNewest + + PreserveNewest + PreserveNewest @@ -940,6 +946,18 @@ PreserveNewest + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + PreserveNewest @@ -1144,6 +1162,18 @@ PreserveNewest + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + PreserveNewest @@ -1210,6 +1240,45 @@ PreserveNewest + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + PreserveNewest @@ -1336,9 +1405,6 @@ PreserveNewest - - PreserveNewest - PreserveNewest @@ -1348,9 +1414,24 @@ PreserveNewest - - - + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + Never + + + PreserveNewest + diff --git a/Barotrauma/BarotraumaShared/Content/Characters/Human/human.xml b/Barotrauma/BarotraumaShared/Content/Characters/Human/human.xml index 8cd39e6fd..929e6f009 100644 --- a/Barotrauma/BarotraumaShared/Content/Characters/Human/human.xml +++ b/Barotrauma/BarotraumaShared/Content/Characters/Human/human.xml @@ -65,7 +65,7 @@ - + @@ -80,7 +80,7 @@ - + diff --git a/Barotrauma/BarotraumaShared/Content/Characters/Human/humanhusk.xml b/Barotrauma/BarotraumaShared/Content/Characters/Human/humanhusk.xml index 33e8bad60..ae252d2e7 100644 --- a/Barotrauma/BarotraumaShared/Content/Characters/Human/humanhusk.xml +++ b/Barotrauma/BarotraumaShared/Content/Characters/Human/humanhusk.xml @@ -73,7 +73,7 @@ - + @@ -88,7 +88,7 @@ - + diff --git a/Barotrauma/BarotraumaShared/Content/Characters/Husk/husk.xml b/Barotrauma/BarotraumaShared/Content/Characters/Husk/husk.xml index c79e29116..a94590bd6 100644 --- a/Barotrauma/BarotraumaShared/Content/Characters/Husk/husk.xml +++ b/Barotrauma/BarotraumaShared/Content/Characters/Husk/husk.xml @@ -76,7 +76,7 @@ - + @@ -88,7 +88,7 @@ - + diff --git a/Barotrauma/BarotraumaShared/Content/Items/Artifacts/artifacts.xml b/Barotrauma/BarotraumaShared/Content/Items/Artifacts/artifacts.xml index 47f7cb4fe..da01ce8ce 100644 --- a/Barotrauma/BarotraumaShared/Content/Items/Artifacts/artifacts.xml +++ b/Barotrauma/BarotraumaShared/Content/Items/Artifacts/artifacts.xml @@ -95,33 +95,40 @@ tags="alien,smallitem,oxygensource" impacttolerance="8"> + + + + + + + - + - + + name="Sulphurite Shard" + category="Alien" + + tags="alien,smallitem" + impacttolerance="8" + spritecolor="1.0,0.0,0.0,1.0"> - - - + + + @@ -130,7 +137,7 @@ - + - + @@ -215,7 +222,7 @@ - + diff --git a/Barotrauma/BarotraumaShared/Content/Items/Button/button.png b/Barotrauma/BarotraumaShared/Content/Items/Button/button.png index e73ef0aed..b47787c54 100644 Binary files a/Barotrauma/BarotraumaShared/Content/Items/Button/button.png and b/Barotrauma/BarotraumaShared/Content/Items/Button/button.png differ diff --git a/Barotrauma/BarotraumaShared/Content/Items/Button/button.xml b/Barotrauma/BarotraumaShared/Content/Items/Button/button.xml index c2e14f374..945031ae1 100644 --- a/Barotrauma/BarotraumaShared/Content/Items/Button/button.xml +++ b/Barotrauma/BarotraumaShared/Content/Items/Button/button.xml @@ -1,33 +1,66 @@ - + + - + - - - - + + + + - + - - - - + + + + - - - - + + + + - - - - - \ No newline at end of file + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Barotrauma/BarotraumaShared/Content/Items/Button/switch.ogg b/Barotrauma/BarotraumaShared/Content/Items/Button/switch.ogg new file mode 100644 index 000000000..83e99e918 Binary files /dev/null and b/Barotrauma/BarotraumaShared/Content/Items/Button/switch.ogg differ diff --git a/Barotrauma/BarotraumaShared/Content/Items/Diving/divinggear.xml b/Barotrauma/BarotraumaShared/Content/Items/Diving/divinggear.xml index 3e81f150e..e2efdb1c1 100644 --- a/Barotrauma/BarotraumaShared/Content/Items/Diving/divinggear.xml +++ b/Barotrauma/BarotraumaShared/Content/Items/Diving/divinggear.xml @@ -68,6 +68,14 @@ fireproof="true" description="An atmospheric diving suit capable of withstanding the immense pressure under Europa's crust."> + + + + + + + + @@ -89,8 +97,8 @@ - - + + @@ -126,8 +134,9 @@ - + + diff --git a/Barotrauma/BarotraumaShared/Content/Items/Door/doorBreak1.ogg b/Barotrauma/BarotraumaShared/Content/Items/Door/doorBreak1.ogg new file mode 100644 index 000000000..fb1517e66 Binary files /dev/null and b/Barotrauma/BarotraumaShared/Content/Items/Door/doorBreak1.ogg differ diff --git a/Barotrauma/BarotraumaShared/Content/Items/Door/doorBreak2.ogg b/Barotrauma/BarotraumaShared/Content/Items/Door/doorBreak2.ogg new file mode 100644 index 000000000..4db93332b Binary files /dev/null and b/Barotrauma/BarotraumaShared/Content/Items/Door/doorBreak2.ogg differ diff --git a/Barotrauma/BarotraumaShared/Content/Items/Door/doors.xml b/Barotrauma/BarotraumaShared/Content/Items/Door/doors.xml index ad2901931..53f3726b8 100644 --- a/Barotrauma/BarotraumaShared/Content/Items/Door/doors.xml +++ b/Barotrauma/BarotraumaShared/Content/Items/Door/doors.xml @@ -6,13 +6,16 @@ - + + + + @@ -37,13 +40,16 @@ - + + + + @@ -68,13 +74,16 @@ - + + + + @@ -103,6 +112,9 @@ + + + @@ -134,6 +146,9 @@ + + + @@ -158,5 +173,39 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Barotrauma/BarotraumaShared/Content/Items/Door/duct.ogg b/Barotrauma/BarotraumaShared/Content/Items/Door/duct.ogg new file mode 100644 index 000000000..9ca48003e Binary files /dev/null and b/Barotrauma/BarotraumaShared/Content/Items/Door/duct.ogg differ diff --git a/Barotrauma/BarotraumaShared/Content/Items/Door/duct.png b/Barotrauma/BarotraumaShared/Content/Items/Door/duct.png new file mode 100644 index 000000000..284838e56 Binary files /dev/null and b/Barotrauma/BarotraumaShared/Content/Items/Door/duct.png differ diff --git a/Barotrauma/BarotraumaShared/Content/Items/Door/ductBreak.ogg b/Barotrauma/BarotraumaShared/Content/Items/Door/ductBreak.ogg new file mode 100644 index 000000000..f17f9734f Binary files /dev/null and b/Barotrauma/BarotraumaShared/Content/Items/Door/ductBreak.ogg differ diff --git a/Barotrauma/BarotraumaShared/Content/Items/Electricity/signalcomp.png b/Barotrauma/BarotraumaShared/Content/Items/Electricity/signalcomp.png index e6d317588..e49db8b05 100644 Binary files a/Barotrauma/BarotraumaShared/Content/Items/Electricity/signalcomp.png and b/Barotrauma/BarotraumaShared/Content/Items/Electricity/signalcomp.png differ diff --git a/Barotrauma/BarotraumaShared/Content/Items/Electricity/signalitems.xml b/Barotrauma/BarotraumaShared/Content/Items/Electricity/signalitems.xml index 687e98788..b7cd52e1c 100644 --- a/Barotrauma/BarotraumaShared/Content/Items/Electricity/signalitems.xml +++ b/Barotrauma/BarotraumaShared/Content/Items/Electricity/signalitems.xml @@ -99,6 +99,11 @@ price="100" description="Field-programmable gate array - a multi-purpose circuit which can be reconfigured for use in a large variety of electrical devices."> + + + + + @@ -335,7 +340,7 @@ - + @@ -366,7 +371,7 @@ - + @@ -382,6 +387,37 @@ + + + + + + + + + + + + + + + + + + + + + + + - + diff --git a/Barotrauma/BarotraumaShared/Content/Items/Fabricators/fabricators.xml b/Barotrauma/BarotraumaShared/Content/Items/Fabricators/fabricators.xml index 9ccb70b2f..305c61450 100644 --- a/Barotrauma/BarotraumaShared/Content/Items/Fabricators/fabricators.xml +++ b/Barotrauma/BarotraumaShared/Content/Items/Fabricators/fabricators.xml @@ -19,6 +19,9 @@ + + + @@ -33,10 +36,26 @@ + + + + + + + + + + + + + + + + @@ -45,6 +64,7 @@ + @@ -54,25 +74,42 @@ - - - - - - + + - + + + + + + + + + + + + + - + + + + + + + + + + @@ -124,6 +161,10 @@ + + + + @@ -140,11 +181,17 @@ + + + + + + - + diff --git a/Barotrauma/BarotraumaShared/Content/Items/Jobgear/misc.xml b/Barotrauma/BarotraumaShared/Content/Items/Jobgear/misc.xml index c94e03422..372af242b 100644 --- a/Barotrauma/BarotraumaShared/Content/Items/Jobgear/misc.xml +++ b/Barotrauma/BarotraumaShared/Content/Items/Jobgear/misc.xml @@ -4,7 +4,9 @@ category="Equipment" tags="smallitem" - description="Allows remote communication between the crew."> + description="Allows remote communication between the crew." + + price="10"> @@ -39,6 +41,10 @@ + + + + @@ -56,6 +62,12 @@ + + + + + + @@ -72,9 +84,12 @@ - - + + + + + diff --git a/Barotrauma/BarotraumaShared/Content/Items/Medical/medical.xml b/Barotrauma/BarotraumaShared/Content/Items/Medical/medical.xml index e7e20a0a4..8e1510ba5 100644 --- a/Barotrauma/BarotraumaShared/Content/Items/Medical/medical.xml +++ b/Barotrauma/BarotraumaShared/Content/Items/Medical/medical.xml @@ -1,5 +1,6 @@  - + + - + + + + + - + + + + + @@ -83,17 +94,139 @@ - + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + @@ -128,12 +261,12 @@ - + - - + + @@ -155,11 +288,11 @@ - + - - + + @@ -178,181 +311,8 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + @@ -370,27 +330,157 @@ - - + + + description="An antiparasitic drug used in the treatment of husk parasite infections. Might require higher dosage to cure the infection at later stages." + price="300"> - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -402,52 +492,85 @@ spritecolor="0.0,0.0,0.0,1.0" Tags="smallitem,chem,medical" description="Dormant eggs of the Europan lifeform colloquially referred to as 'husk parasite'." - price="200"> + price="2000"> - + + + + description="A highly potent neurotoxin." + price="1000"> - - + + + name="Nitroglycerin" + category="Material" + description="A highly unstable liquid that may explode when subjected to heat or physical shock." + spritecolor="1.0,1.0,1.0,1.0" + Tags="smallitem,chem,medical" + impacttolerance="4"> - + - + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Barotrauma/BarotraumaShared/Content/Items/Reactor/reactor.xml b/Barotrauma/BarotraumaShared/Content/Items/Reactor/reactor.xml index 567d58a35..75c6100ad 100644 --- a/Barotrauma/BarotraumaShared/Content/Items/Reactor/reactor.xml +++ b/Barotrauma/BarotraumaShared/Content/Items/Reactor/reactor.xml @@ -61,7 +61,9 @@ - + + + @@ -78,7 +80,7 @@ - + @@ -92,7 +94,7 @@ + price="50"> diff --git a/Barotrauma/BarotraumaShared/Content/Items/Tools/tools.xml b/Barotrauma/BarotraumaShared/Content/Items/Tools/tools.xml index 1c05f3b14..580b856f0 100644 --- a/Barotrauma/BarotraumaShared/Content/Items/Tools/tools.xml +++ b/Barotrauma/BarotraumaShared/Content/Items/Tools/tools.xml @@ -181,7 +181,7 @@ - + @@ -198,7 +198,7 @@ - + @@ -271,8 +271,10 @@ tags="smallitem"> - - + + + + diff --git a/Barotrauma/BarotraumaShared/Content/Items/Weapons/explosives.xml b/Barotrauma/BarotraumaShared/Content/Items/Weapons/explosives.xml index 24444fb0d..0eed0c613 100644 --- a/Barotrauma/BarotraumaShared/Content/Items/Weapons/explosives.xml +++ b/Barotrauma/BarotraumaShared/Content/Items/Weapons/explosives.xml @@ -104,31 +104,4 @@ - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Barotrauma/BarotraumaShared/Content/Items/Weapons/weapons.xml b/Barotrauma/BarotraumaShared/Content/Items/Weapons/weapons.xml index ea239b874..d393a601a 100644 --- a/Barotrauma/BarotraumaShared/Content/Items/Weapons/weapons.xml +++ b/Barotrauma/BarotraumaShared/Content/Items/Weapons/weapons.xml @@ -144,6 +144,12 @@ price="200" tags="smallitem,weapon"> + + + + + + @@ -161,6 +167,12 @@ category="Equipment" tags="smallitem,weapon"> + + + + + + @@ -222,8 +234,8 @@ - - + + @@ -242,8 +254,8 @@ - - + + diff --git a/Barotrauma/BarotraumaShared/Content/Sounds/Damage/HitClown1.ogg b/Barotrauma/BarotraumaShared/Content/Sounds/Damage/HitClown1.ogg new file mode 100644 index 000000000..f38004a88 Binary files /dev/null and b/Barotrauma/BarotraumaShared/Content/Sounds/Damage/HitClown1.ogg differ diff --git a/Barotrauma/BarotraumaShared/Content/Sounds/Damage/HitClown2.ogg b/Barotrauma/BarotraumaShared/Content/Sounds/Damage/HitClown2.ogg new file mode 100644 index 000000000..81ff5864b Binary files /dev/null and b/Barotrauma/BarotraumaShared/Content/Sounds/Damage/HitClown2.ogg differ diff --git a/Barotrauma/BarotraumaShared/Content/Sounds/Damage/HitClown3.ogg b/Barotrauma/BarotraumaShared/Content/Sounds/Damage/HitClown3.ogg new file mode 100644 index 000000000..210e633a1 Binary files /dev/null and b/Barotrauma/BarotraumaShared/Content/Sounds/Damage/HitClown3.ogg differ diff --git a/Barotrauma/BarotraumaShared/Content/Sounds/Damage/HitClown4.ogg b/Barotrauma/BarotraumaShared/Content/Sounds/Damage/HitClown4.ogg new file mode 100644 index 000000000..8d0294b86 Binary files /dev/null and b/Barotrauma/BarotraumaShared/Content/Sounds/Damage/HitClown4.ogg differ diff --git a/Barotrauma/BarotraumaShared/Content/Sounds/Footsteps/Armor/armor-01.ogg b/Barotrauma/BarotraumaShared/Content/Sounds/Footsteps/Armor/armor-01.ogg new file mode 100644 index 000000000..8ef4ceda7 Binary files /dev/null and b/Barotrauma/BarotraumaShared/Content/Sounds/Footsteps/Armor/armor-01.ogg differ diff --git a/Barotrauma/BarotraumaShared/Content/Sounds/Footsteps/Armor/armor-02.ogg b/Barotrauma/BarotraumaShared/Content/Sounds/Footsteps/Armor/armor-02.ogg new file mode 100644 index 000000000..b37028ebd Binary files /dev/null and b/Barotrauma/BarotraumaShared/Content/Sounds/Footsteps/Armor/armor-02.ogg differ diff --git a/Barotrauma/BarotraumaShared/Content/Sounds/Footsteps/Armor/armor-03.ogg b/Barotrauma/BarotraumaShared/Content/Sounds/Footsteps/Armor/armor-03.ogg new file mode 100644 index 000000000..9db560df8 Binary files /dev/null and b/Barotrauma/BarotraumaShared/Content/Sounds/Footsteps/Armor/armor-03.ogg differ diff --git a/Barotrauma/BarotraumaShared/Content/Sounds/Footsteps/Clown/clown-01.ogg b/Barotrauma/BarotraumaShared/Content/Sounds/Footsteps/Clown/clown-01.ogg new file mode 100644 index 000000000..13dc7da09 Binary files /dev/null and b/Barotrauma/BarotraumaShared/Content/Sounds/Footsteps/Clown/clown-01.ogg differ diff --git a/Barotrauma/BarotraumaShared/Content/Sounds/Footsteps/Clown/clown-02.ogg b/Barotrauma/BarotraumaShared/Content/Sounds/Footsteps/Clown/clown-02.ogg new file mode 100644 index 000000000..e6b473665 Binary files /dev/null and b/Barotrauma/BarotraumaShared/Content/Sounds/Footsteps/Clown/clown-02.ogg differ diff --git a/Barotrauma/BarotraumaShared/Content/Sounds/Footsteps/Metal/metal-01.ogg b/Barotrauma/BarotraumaShared/Content/Sounds/Footsteps/Metal/metal-01.ogg new file mode 100644 index 000000000..df55e6444 Binary files /dev/null and b/Barotrauma/BarotraumaShared/Content/Sounds/Footsteps/Metal/metal-01.ogg differ diff --git a/Barotrauma/BarotraumaShared/Content/Sounds/Footsteps/Metal/metal-02.ogg b/Barotrauma/BarotraumaShared/Content/Sounds/Footsteps/Metal/metal-02.ogg new file mode 100644 index 000000000..eb4d0b74d Binary files /dev/null and b/Barotrauma/BarotraumaShared/Content/Sounds/Footsteps/Metal/metal-02.ogg differ diff --git a/Barotrauma/BarotraumaShared/Content/Sounds/Footsteps/Metal/metal-03.ogg b/Barotrauma/BarotraumaShared/Content/Sounds/Footsteps/Metal/metal-03.ogg new file mode 100644 index 000000000..f2bd383dd Binary files /dev/null and b/Barotrauma/BarotraumaShared/Content/Sounds/Footsteps/Metal/metal-03.ogg differ diff --git a/Barotrauma/BarotraumaShared/Content/Sounds/Footsteps/Metal/metal-04.ogg b/Barotrauma/BarotraumaShared/Content/Sounds/Footsteps/Metal/metal-04.ogg new file mode 100644 index 000000000..1011a26d5 Binary files /dev/null and b/Barotrauma/BarotraumaShared/Content/Sounds/Footsteps/Metal/metal-04.ogg differ diff --git a/Barotrauma/BarotraumaShared/Content/Sounds/Footsteps/Metal/metal-05.ogg b/Barotrauma/BarotraumaShared/Content/Sounds/Footsteps/Metal/metal-05.ogg new file mode 100644 index 000000000..9662054dc Binary files /dev/null and b/Barotrauma/BarotraumaShared/Content/Sounds/Footsteps/Metal/metal-05.ogg differ diff --git a/Barotrauma/BarotraumaShared/Content/Sounds/Footsteps/Metal/metal-06.ogg b/Barotrauma/BarotraumaShared/Content/Sounds/Footsteps/Metal/metal-06.ogg new file mode 100644 index 000000000..2ee071ba8 Binary files /dev/null and b/Barotrauma/BarotraumaShared/Content/Sounds/Footsteps/Metal/metal-06.ogg differ diff --git a/Barotrauma/BarotraumaShared/Content/Sounds/Footsteps/Metal/metal-07.ogg b/Barotrauma/BarotraumaShared/Content/Sounds/Footsteps/Metal/metal-07.ogg new file mode 100644 index 000000000..318070139 Binary files /dev/null and b/Barotrauma/BarotraumaShared/Content/Sounds/Footsteps/Metal/metal-07.ogg differ diff --git a/Barotrauma/BarotraumaShared/Content/step.ogg b/Barotrauma/BarotraumaShared/Content/Sounds/Footsteps/step.ogg similarity index 100% rename from Barotrauma/BarotraumaShared/Content/step.ogg rename to Barotrauma/BarotraumaShared/Content/Sounds/Footsteps/step.ogg diff --git a/Barotrauma/BarotraumaShared/Content/Sounds/sounds.xml b/Barotrauma/BarotraumaShared/Content/Sounds/sounds.xml index d4156d5d9..b8b798e06 100644 --- a/Barotrauma/BarotraumaShared/Content/Sounds/sounds.xml +++ b/Barotrauma/BarotraumaShared/Content/Sounds/sounds.xml @@ -38,7 +38,11 @@ - + + + + + @@ -52,6 +56,22 @@ + + + + + + + + + + + + + + + + diff --git a/Barotrauma/BarotraumaShared/Source/Characters/Animation/HumanoidAnimController.cs b/Barotrauma/BarotraumaShared/Source/Characters/Animation/HumanoidAnimController.cs index 8a9ec6738..c5633c260 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/Animation/HumanoidAnimController.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/Animation/HumanoidAnimController.cs @@ -1000,7 +1000,7 @@ namespace Barotrauma { target.AddDamage(CauseOfDeath.Bloodloss, 1.0f, character); #if CLIENT - SoundPlayer.PlayDamageSound(DamageSoundType.LimbBlunt, 25.0f, targetTorso.body); + SoundPlayer.PlayDamageSound("LimbBlunt", 25.0f, targetTorso.body); for (int i = 0; i < 4; i++) { diff --git a/Barotrauma/BarotraumaShared/Source/Characters/Character.cs b/Barotrauma/BarotraumaShared/Source/Characters/Character.cs index 68dba348e..de458f0aa 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/Character.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/Character.cs @@ -371,6 +371,7 @@ namespace Barotrauma { if (!MathUtils.IsValid(value)) return; if (GameMain.Client != null) return; + if (!DoesBleed) return; float newBleeding = MathHelper.Clamp(value, 0.0f, 5.0f); //if (newBleeding == bleeding) return; @@ -1618,6 +1619,15 @@ namespace Barotrauma lowPassMultiplier = MathHelper.Lerp(lowPassMultiplier, 1.0f, 0.1f); + if (DoesBleed) + { + Health -= bleeding * deltaTime; + Bleeding -= BleedingDecreaseSpeed * deltaTime; + } + + if (health <= minHealth) Kill(CauseOfDeath.Bloodloss); + + if (!IsDead) LockHands = false; //CPR stuff is handled in the UpdateCPR function in HumanoidAnimController } diff --git a/Barotrauma/BarotraumaShared/Source/Characters/DamageModifier.cs b/Barotrauma/BarotraumaShared/Source/Characters/DamageModifier.cs index e97d57971..2710e7a48 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/DamageModifier.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/DamageModifier.cs @@ -49,8 +49,8 @@ namespace Barotrauma #if CLIENT - [Serialize(DamageSoundType.None, false)] - public DamageSoundType DamageSoundType + [Serialize("", false)] + public string DamageSound { get; private set; diff --git a/Barotrauma/BarotraumaShared/Source/Characters/DelayedEffect.cs b/Barotrauma/BarotraumaShared/Source/Characters/DelayedEffect.cs index e0d68a6be..7dd32eca7 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/DelayedEffect.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/DelayedEffect.cs @@ -3,23 +3,19 @@ using System.Xml.Linq; namespace Barotrauma { + class DelayedListElement + { + public DelayedEffect Parent; + public Entity Entity; + public List Targets; + public float StartTimer; + } class DelayedEffect : StatusEffect { - public static List List = new List(); + public static List DelayList = new List(); private float delay; - private float startTimer; - - private Entity entity; - - private List targets; - - public float StartTimer - { - get { return startTimer; } - } - public DelayedEffect(XElement element) : base(element) { @@ -28,25 +24,36 @@ namespace Barotrauma public override void Apply(ActionType type, float deltaTime, Entity entity, List targets) { - if (this.type != type) return; - - startTimer = delay; - this.entity = entity; + if (this.type != type || !HasRequiredItems(entity)) return; + if (!base.Stackable && DelayList.Find(d => d.Parent == this && d.Entity == entity && d.Targets == targets) != null) return; - this.targets = targets; + DelayedListElement element = new DelayedListElement(); + element.Parent = this; + element.StartTimer = delay; + element.Entity = entity; + element.Targets = targets; - List.Add(this); + DelayList.Add(element); } - public void Update(float deltaTime) + public static void Update(float deltaTime) { - startTimer -= deltaTime; + for (int i = DelayList.Count - 1; i >= 0; i--) + { + DelayedListElement element = DelayList[i]; + if (element.Parent.CheckConditionalAlways && !element.Parent.HasRequiredConditions(element.Targets)) + { + DelayList.Remove(element); + continue; + } - if (startTimer > 0.0f) return; + element.StartTimer -= deltaTime; - base.Apply(1.0f, entity, targets); - List.Remove(this); + if (element.StartTimer > 0.0f) continue; + + element.Parent.Apply(1.0f, element.Entity, element.Targets); + DelayList.Remove(element); + } } - } -} +} \ No newline at end of file diff --git a/Barotrauma/BarotraumaShared/Source/Characters/Limb.cs b/Barotrauma/BarotraumaShared/Source/Characters/Limb.cs index efeddcd85..3e0ef35fc 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/Limb.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/Limb.cs @@ -373,13 +373,13 @@ namespace Barotrauma #if CLIENT if (playSound) { - DamageSoundType damageSoundType = (damageType == DamageType.Blunt) ? DamageSoundType.LimbBlunt : DamageSoundType.LimbSlash; + string damageSoundType = (damageType == DamageType.Blunt) ? "LimbBlunt" : "LimbSlash"; foreach (DamageModifier damageModifier in appliedDamageModifiers) { - if (damageModifier.DamageSoundType != DamageSoundType.None) + if (!string.IsNullOrWhiteSpace(damageModifier.DamageSound)) { - damageSoundType = damageModifier.DamageSoundType; + damageSoundType = damageModifier.DamageSound; break; } } @@ -594,12 +594,6 @@ namespace Barotrauma } #if CLIENT - if (hitSound != null) - { - hitSound.Remove(); - hitSound = null; - } - if (LightSource != null) { LightSource.Remove(); diff --git a/Barotrauma/BarotraumaShared/Source/Characters/StatusEffect.cs b/Barotrauma/BarotraumaShared/Source/Characters/StatusEffect.cs index 1ef9c181f..16655024c 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/StatusEffect.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/StatusEffect.cs @@ -9,6 +9,93 @@ using Barotrauma.Particles; namespace Barotrauma { + class DurationListElement + { + public StatusEffect Parent; + public Entity Entity; + public List Targets; + public float StartTimer; + } + partial class PropertyConditional + { + public string Attribute; + public string Operator; + public object Value; + + public PropertyConditional(string Attribute, string Operator, object Value) + { + this.Attribute = Attribute; + this.Operator = Operator; + this.Value = Value; + } + + public bool Matches(SerializableProperty property) + { + if (property.GetValue() == null) + { + DebugConsole.ThrowError("Couldn't compare " + Value.ToString() + " (" + Value.GetType() + ") to property \"" + property.Name + "- property.GetValue() returns null!!"); + return false; + } + Type type = property.GetValue().GetType(); + + float? floatValue = null; + float? floatProperty = null; + if (type == typeof(float) || type == typeof(int)) + { + floatValue = Convert.ToSingle(Value); + floatProperty = Convert.ToSingle(property.GetValue()); + } + + switch (Operator) + { + case "==": + if (property.GetValue().Equals(floatValue == null ? Value : floatValue)) + return true; + break; + case "!=": + if (property.GetValue().Equals(floatValue == null ? Value : floatValue)) + return true; + break; + case ">": + if (floatValue == null) + { + DebugConsole.ThrowError("Couldn't compare " + Value.ToString() + " (" + Value.GetType() + ") to property \"" + property.Name + "\" (" + type + ")! " + + "Make sure the type of the value set in the config files matches the type of the property."); + } + else if (floatProperty > floatValue) + return true; + break; + case "<": + if (floatValue == null) + { + DebugConsole.ThrowError("Couldn't compare " + Value.ToString() + " (" + Value.GetType() + ") to property \"" + property.Name + "\" (" + type + ")! " + + "Make sure the type of the value set in the config files matches the type of the property."); + } + else if (floatProperty < floatValue) + return true; + break; + case ">=": + if (floatValue == null) + { + DebugConsole.ThrowError("Couldn't compare " + Value.ToString() + " (" + Value.GetType() + ") to property \"" + property.Name + "\" (" + type + ")! " + + "Make sure the type of the value set in the config files matches the type of the property."); + } + else if (floatProperty >= floatValue) + return true; + break; + case "<=": + if (floatValue == null) + { + DebugConsole.ThrowError("Couldn't compare " + Value.ToString() + " (" + Value.GetType() + ") to property \"" + property.Name + "\" (" + type + ")! " + + "Make sure the type of the value set in the config files matches the type of the property."); + } + else if (floatProperty <= floatValue) + return true; + break; + } + return false; + } + } partial class StatusEffect { [Flags] @@ -32,15 +119,24 @@ namespace Barotrauma public string[] propertyNames; private object[] propertyEffects; + List propertyConditionals; + private bool setValue; private bool disableDeltaTime; private HashSet onContainingNames; + private HashSet tags; private readonly float duration; + public static List DurationList = new List(); - private readonly bool useItem; + public bool CheckConditionalAlways; //Always do the conditional checks for the duration/delay. If false, only check conditional on apply. + + public bool Stackable; //Can the same status effect be applied several times to the same targets? + + private readonly int useItemCount; + private readonly int cancelStatusEffect; public readonly ActionType type; @@ -63,6 +159,24 @@ namespace Barotrauma get { return onContainingNames; } } + public string Tags + { + get { return string.Join(",", tags); } + set + { + tags.Clear(); + if (value == null) return; + + string[] newTags = value.Split(','); + foreach (string tag in newTags) + { + string newTag = tag.Trim(); + if (!tags.Contains(newTag)) tags.Add(newTag); + } + + } + } + public static StatusEffect Load(XElement element) { if (element.Attribute("delay")!=null) @@ -76,14 +190,16 @@ namespace Barotrauma protected StatusEffect(XElement element) { requiredItems = new List(); + tags = new HashSet(element.GetAttributeString("tags", "").Split(',')); #if CLIENT particleEmitters = new List(); #endif - IEnumerable attributes = element.Attributes(); + IEnumerable attributes = element.Attributes(); List propertyAttributes = new List(); - + propertyConditionals = new List(); + foreach (XAttribute attribute in attributes) { switch (attribute.Name.ToString()) @@ -133,6 +249,12 @@ namespace Barotrauma case "duration": duration = attribute.GetAttributeFloat(0.0f); break; + case "stackable": + Stackable = attribute.GetAttributeBool(true); + break; + case "checkconditionalalways": + CheckConditionalAlways = attribute.GetAttributeBool(false); + break; case "sound": DebugConsole.ThrowError("Error in StatusEffect " + element.Parent.Name.ToString() + " - sounds should be defined as child elements of the StatusEffect, not as attributes."); @@ -167,7 +289,14 @@ namespace Barotrauma break; case "use": case "useitem": - useItem = true; + useItemCount++; + break; + case "cancel": + case "cancelstatuseffect": + //This only works if there's a conditional checking for status effect tags. There is no way to cancel *all* status effects atm. + cancelStatusEffect = 1; + if (subElement.GetAttributeBool("all", false) == true) + cancelStatusEffect = 2; break; case "requireditem": case "requireditems": @@ -177,6 +306,67 @@ namespace Barotrauma requiredItems.Add(newRequiredItem); break; + case "conditional": + IEnumerable conditionalAttributes = subElement.Attributes(); + foreach(XAttribute attribute in conditionalAttributes) + { + string attributeString = XMLExtensions.GetAttributeObject(attribute).ToString(); + string atStr = attributeString; + string[] splitString = atStr.Split(' '); + string op = splitString[0]; + if (splitString.Length > 0) + { + for (int i=1; i 1 && i < splitString.Length ? " " : ""); + } + } + //thanks xml for not letting me use < or > in attributes :( + switch (op) + { + case "e": + case "eq": + case "equals": + op = "=="; + break; + case "ne": + case "neq": + case "notequals": + case "!": + case "!e": + case "!eq": + case "!equals": + op = "!="; + break; + case "gt": + case "greaterthan": + op = ">"; + break; + case "lt": + case "lessthan": + op = "<"; + break; + case "gte": + case "gteq": + case "greaterthanequals": + op = ">="; + break; + case "lte": + case "lteq": + case "lessthanequals": + op = "<="; + break; + default: + if (op != "==" && op != "!=" && op != ">" && op != "<" && op != ">=" && op != "<=") //Didn't use escape strings or anything + { + atStr = attributeString; //We probably don't even have an operator + op = "=="; + } + break; + } + propertyConditionals.Add(new PropertyConditional(attribute.Name.ToString().ToLowerInvariant(), op, atStr)); + } + break; #if CLIENT case "particleemitter": particleEmitters.Add(new ParticleEmitter(subElement)); @@ -190,7 +380,7 @@ namespace Barotrauma } } - private bool HasRequiredItems(Entity entity) + public virtual bool HasRequiredItems(Entity entity) { if (requiredItems == null) return true; foreach (RelatedItem requiredItem in requiredItems) @@ -209,21 +399,97 @@ namespace Barotrauma return true; } + public virtual bool HasRequiredConditions(List targets) + { + if (!propertyConditionals.Any()) return true; + foreach (ISerializableEntity target in targets) + { + foreach (PropertyConditional pc in propertyConditionals) + { + if (target == null || target.SerializableProperties == null) continue; + + if (!target.SerializableProperties.TryGetValue(pc.Attribute, out SerializableProperty property)) + { + //Do special conditional checks + + string valStr = pc.Value.ToString(); + if (pc.Attribute == "name") + return pc.Operator == "==" ? target.Name == valStr : target.Name != valStr; + + if (pc.Attribute == "speciesname" && target is Character) + return pc.Operator == "==" ? ((Character)target).SpeciesName == valStr : ((Character)target).SpeciesName != valStr; + + if ((pc.Attribute == "hastag" || pc.Attribute == "hastags") && target is Item) + { + string[] readTags = valStr.Split(','); + int matches = 0; + foreach (string tag in readTags) + if (((Item)target).HasTag(tag)) matches++; + + //If operator is == then it needs to match everything, otherwise if its != there must be zero matches. + return pc.Operator == "==" ? matches >= readTags.Length : matches <= 0; + } + + List durations = DurationList.FindAll(d => d.Targets.Contains(target)); + List delays = DelayedEffect.DelayList.FindAll(d => d.Targets.Contains(target)); + + bool success = false; + if (pc.Attribute == "hasstatustag" || pc.Attribute == "hasstatustags" && (durations.Any() || delays.Any())) + { + string[] readTags = valStr.Split(','); + foreach (DurationListElement duration in durations) + { + int matches = 0; + foreach (string tag in readTags) + if (duration.Parent.HasTag(tag)) matches++; + + success = pc.Operator == "==" ? matches >= readTags.Length : matches <= 0; + if (cancelStatusEffect > 0 && success) + DurationList.Remove(duration); + if (cancelStatusEffect != 2) //cancelStatusEffect 1 = only cancel once, cancelStatusEffect 2 = cancel all of matching tags + return success; + } + foreach (DelayedListElement delay in delays) + { + int matches = 0; + foreach (string tag in readTags) + if (delay.Parent.HasTag(tag)) matches++; + + success = pc.Operator == "==" ? matches >= readTags.Length : matches <= 0; + if (cancelStatusEffect > 0 && success) + DelayedEffect.DelayList.Remove(delay); + if (cancelStatusEffect != 2) //ditto + return success; + } + } + return success; + } + else if (!pc.Matches(property)) + return false; + } + } + return true; + } + public virtual void Apply(ActionType type, float deltaTime, Entity entity, ISerializableEntity target) { if (this.type != type || !HasRequiredItems(entity)) return; if (targetNames != null && !targetNames.Contains(target.Name)) return; + if (duration > 0.0f && !Stackable && DurationList.Find(d => d.Parent == this && d.Entity == entity && d.Targets.Contains(target)) != null) return; + List targets = new List(); targets.Add(target); - Apply(deltaTime, entity, targets); + if (!HasRequiredConditions(targets)) return; + + Apply(type, deltaTime, entity, targets); } public virtual void Apply(ActionType type, float deltaTime, Entity entity, List targets) { - if (this.type != type || !HasRequiredItems(entity)) return; + if (this.type != type || !HasRequiredItems(entity) || !HasRequiredConditions(targets)) return; Apply(deltaTime, entity, targets); } @@ -251,35 +517,43 @@ namespace Barotrauma } #endif - if (useItem) + if (useItemCount > 0) { - foreach (Item item in targets.FindAll(t => t is Item).Cast()) + for (int i=0; i t is Character) as Character); - } - } - - foreach (ISerializableEntity target in targets) - { - for (int i = 0; i < propertyNames.Length; i++) - { - SerializableProperty property; - - if (target == null || target.SerializableProperties == null || !target.SerializableProperties.TryGetValue(propertyNames[i], out property)) continue; - - if (duration > 0.0f) + foreach (Item item in targets.FindAll(t => t is Item).Cast()) { - CoroutineManager.StartCoroutine( - ApplyToPropertyOverDuration(duration, property, propertyEffects[i]), "statuseffect"); - - } - else - { - ApplyToProperty(property, propertyEffects[i], deltaTime); + item.Use(deltaTime, targets.FirstOrDefault(t => t is Character) as Character); } } } + if (duration > 0.0f) + { + DurationListElement element = new DurationListElement(); + element.Parent = this; + element.StartTimer = duration; + element.Entity = entity; + element.Targets = targets; + + DurationList.Add(element); + } + else + { + foreach (ISerializableEntity target in targets) + { + for (int i = 0; i < propertyNames.Length; i++) + { + SerializableProperty property; + + if (target == null || target.SerializableProperties == null || !target.SerializableProperties.TryGetValue(propertyNames[i], out property)) continue; + + ApplyToProperty(property, propertyEffects[i], deltaTime); + } + } + } + + if (explosion != null) explosion.Explode(entity.WorldPosition); @@ -308,21 +582,6 @@ namespace Barotrauma #endif } - private IEnumerable ApplyToPropertyOverDuration(float duration, SerializableProperty property, object value) - { - float timer = duration; - while (timer > 0.0f) - { - ApplyToProperty(property, value, CoroutineManager.UnscaledDeltaTime); - - timer -= CoroutineManager.DeltaTime; - - yield return CoroutineStatus.Running; - } - - yield return CoroutineStatus.Success; - } - private void ApplyToProperty(SerializableProperty property, object value, float deltaTime) { if (disableDeltaTime || setValue) deltaTime = 1.0f; @@ -359,9 +618,33 @@ namespace Barotrauma public static void UpdateAll(float deltaTime) { - for (int i = DelayedEffect.List.Count-1; i>= 0; i--) + DelayedEffect.Update(deltaTime); + for (int i = DurationList.Count - 1; i >= 0; i--) { - DelayedEffect.List[i].Update(deltaTime); + DurationListElement element = DurationList[i]; + + if (element.Parent.CheckConditionalAlways && !element.Parent.HasRequiredConditions(element.Targets)) + { + DurationList.Remove(element); + continue; + } + + foreach (ISerializableEntity target in element.Targets) + { + for (int n = 0; n < element.Parent.propertyNames.Length; n++) + { + SerializableProperty property; + + if (target == null || target.SerializableProperties == null || !target.SerializableProperties.TryGetValue(element.Parent.propertyNames[n], out property)) continue; + + element.Parent.ApplyToProperty(property, element.Parent.propertyEffects[n], CoroutineManager.UnscaledDeltaTime); + } + } + + element.StartTimer -= deltaTime; + + if (element.StartTimer > 0.0f) continue; + DurationList.Remove(element); } } @@ -369,5 +652,18 @@ namespace Barotrauma { CoroutineManager.StopCoroutines("statuseffect"); } + + public void AddTag(string tag) + { + if (tags.Contains(tag)) return; + tags.Add(tag); + } + + public bool HasTag(string tag) + { + if (tag == null) return true; + + return (tags.Contains(tag) || tags.Contains(tag.ToLowerInvariant())); + } } } diff --git a/Barotrauma/BarotraumaShared/Source/Items/Components/Door.cs b/Barotrauma/BarotraumaShared/Source/Items/Components/Door.cs index fbb0e3fe4..c78fe89b2 100644 --- a/Barotrauma/BarotraumaShared/Source/Items/Components/Door.cs +++ b/Barotrauma/BarotraumaShared/Source/Items/Components/Door.cs @@ -203,8 +203,23 @@ namespace Barotrauma.Items.Components #endif } + public override bool HasRequiredItems(Character character, bool addMessage) + { + if (item.Condition <= 0.0f) return true; //For repairing + + //this is a bit pointless atm because if canBePicked is false it won't allow you to do Pick() anyway, however it's still good for future-proofing. + return requiredItems.Any() ? base.HasRequiredItems(character, addMessage) : canBePicked; + } + + public override bool Pick(Character picker) + { + return item.Condition <= 0.0f ? true : base.Pick(picker); + } + public override bool OnPicked(Character picker) { + if (item.Condition <= 0.0f) return true; //repairs + SetState(predictedState == null ? !isOpen : !predictedState.Value, false, true); //crowbar function #if CLIENT PlaySound(ActionType.OnPicked, item.WorldPosition); @@ -369,7 +384,7 @@ namespace Barotrauma.Items.Components if (Math.Sign(diff) != dir) { #if CLIENT - SoundPlayer.PlayDamageSound(DamageSoundType.LimbBlunt, 1.0f, body); + SoundPlayer.PlayDamageSound("LimbBlunt", 1.0f, body); #endif if (isHorizontal) diff --git a/Barotrauma/BarotraumaShared/Source/Items/Components/Holdable/MeleeWeapon.cs b/Barotrauma/BarotraumaShared/Source/Items/Components/Holdable/MeleeWeapon.cs index 38f8ca61a..ce564e36b 100644 --- a/Barotrauma/BarotraumaShared/Source/Items/Components/Holdable/MeleeWeapon.cs +++ b/Barotrauma/BarotraumaShared/Source/Items/Components/Holdable/MeleeWeapon.cs @@ -215,6 +215,7 @@ namespace Barotrauma.Items.Components { Character targetCharacter = null; Limb targetLimb = null; + Structure targetStructure = null; if (f2.Body.UserData is Limb) { @@ -224,8 +225,12 @@ namespace Barotrauma.Items.Components } else if (f2.Body.UserData is Character) { - targetCharacter = (Character)f2.Body.UserData; + targetLimb = targetCharacter.AnimController.GetLimb(LimbType.Torso); //Otherwise armor can be bypassed in strange ways + } + else if (f2.Body.UserData is Structure) + { + targetStructure = (Structure)f2.Body.UserData; } else { @@ -236,14 +241,22 @@ namespace Barotrauma.Items.Components if (attack != null) { - if (targetLimb == null) + if (targetLimb != null) { attack.DoDamageToLimb(user, targetLimb, item.WorldPosition, 1.0f); } - else + else if (targetCharacter != null) { attack.DoDamage(user, targetCharacter, item.WorldPosition, 1.0f); } + else if (targetStructure != null) + { + attack.DoDamage(user, targetStructure, item.WorldPosition, 1.0f); + } + else + { + return false; + } } RestoreCollision(); @@ -251,7 +264,7 @@ namespace Barotrauma.Items.Components if (GameMain.Client != null) return true; - if (GameMain.Server != null) + if (GameMain.Server != null && targetCharacter != null) //TODO: Log structure hits { GameMain.Server.CreateEntityEvent(item, new object[] { Networking.NetEntityEvent.Type.ApplyStatusEffect, ActionType.OnUse, targetCharacter.ID }); @@ -263,8 +276,9 @@ namespace Barotrauma.Items.Components logStr += " on " + targetCharacter.LogName + "."; Networking.GameServer.Log(logStr, Networking.ServerLog.MessageType.Attack); } - - ApplyStatusEffects(ActionType.OnUse, 1.0f, targetLimb.character); + + if (targetCharacter != null) //TODO: Allow OnUse to happen on structures too maybe?? + ApplyStatusEffects(ActionType.OnUse, 1.0f, targetCharacter != null ? targetCharacter : null); return true; } diff --git a/Barotrauma/BarotraumaShared/Source/Items/Components/ItemComponent.cs b/Barotrauma/BarotraumaShared/Source/Items/Components/ItemComponent.cs index d30282e3b..c92971c4f 100644 --- a/Barotrauma/BarotraumaShared/Source/Items/Components/ItemComponent.cs +++ b/Barotrauma/BarotraumaShared/Source/Items/Components/ItemComponent.cs @@ -30,6 +30,8 @@ namespace Barotrauma.Items.Components protected bool canBePicked; protected bool canBeSelected; + protected bool canBeCombined; + protected bool removeOnCombined; public bool WasUsed; @@ -47,7 +49,7 @@ namespace Barotrauma.Items.Components private string msg; - [Serialize(0.0f, false)] + [Editable, Serialize(0.0f, false)] public float PickingTime { get; @@ -103,7 +105,7 @@ namespace Barotrauma.Items.Components } } - [Serialize(false, false)] + [Editable, Serialize(false, false)] //Editable for doors to do their magic public bool CanBePicked { get { return canBePicked; } @@ -124,6 +126,22 @@ namespace Barotrauma.Items.Components set { canBeSelected = value; } } + //Transfer conditions between same prefab items + [Serialize(false, false)] + public bool CanBeCombined + { + get { return canBeCombined; } + set { canBeCombined = value; } + } + + //Remove item if combination results in 0 condition + [Serialize(false, false)] + public bool RemoveOnCombined + { + get { return removeOnCombined; } + set { removeOnCombined = value; } + } + public InputType PickKey { get; @@ -153,7 +171,7 @@ namespace Barotrauma.Items.Components get { return name; } } - [Serialize("", false)] + [Editable, Serialize("", false)] public string Msg { get { return msg; } @@ -196,7 +214,7 @@ namespace Barotrauma.Items.Components try { - string pickKeyStr = element.GetAttributeString("selectkey", "Select"); + string pickKeyStr = element.GetAttributeString("pickkey", "Select"); pickKeyStr = ToolBox.ConvertInputType(pickKeyStr); PickKey = (InputType)Enum.Parse(typeof(InputType),pickKeyStr, true); } @@ -323,6 +341,43 @@ namespace Barotrauma.Items.Components public virtual bool Combine(Item item) { + if (canBeCombined && this.item.Prefab == item.Prefab && item.Condition > 0.0f && this.item.Condition > 0.0f) + { + float transferAmount = 0.0f; + if (this.Item.Condition <= item.Condition) + transferAmount = Math.Min(item.Condition, this.item.Prefab.Health - this.item.Condition); + else + transferAmount = -Math.Min(this.item.Condition, item.Prefab.Health - item.Condition); + + if (transferAmount == 0.0f) + return false; + this.Item.Condition += transferAmount; + item.Condition -= transferAmount; + if (removeOnCombined) + { + if (item.Condition <= 0.0f) + { + if (item.ParentInventory != null) + { + Character owner = (Character)item.ParentInventory.Owner; + if (owner != null && owner.HasSelectedItem(item)) item.Unequip(owner); + item.ParentInventory.RemoveItem(item); + } + Entity.Spawner.AddToRemoveQueue(item); + } + if (this.Item.Condition <= 0.0f) + { + if (this.Item.ParentInventory != null) + { + Character owner = (Character)this.Item.ParentInventory.Owner; + if (owner != null && owner.HasSelectedItem(this.Item)) this.Item.Unequip(owner); + this.Item.ParentInventory.RemoveItem(this.Item); + } + Entity.Spawner.AddToRemoveQueue(this.Item); + } + } + return true; + } return false; } @@ -437,7 +492,7 @@ namespace Barotrauma.Items.Components return true; } - public bool HasRequiredItems(Character character, bool addMessage) + public virtual bool HasRequiredItems(Character character, bool addMessage) { if (!requiredItems.Any()) return true; if (character.Inventory == null) return false; diff --git a/Barotrauma/BarotraumaShared/Source/Items/Components/ItemContainer.cs b/Barotrauma/BarotraumaShared/Source/Items/Components/ItemContainer.cs index e427d8aa2..30923113c 100644 --- a/Barotrauma/BarotraumaShared/Source/Items/Components/ItemContainer.cs +++ b/Barotrauma/BarotraumaShared/Source/Items/Components/ItemContainer.cs @@ -170,7 +170,7 @@ namespace Barotrauma.Items.Components if (effect.Targets.HasFlag(StatusEffect.TargetType.This)) effect.Apply(ActionType.OnContaining, deltaTime, item, item.AllPropertyObjects); if (effect.Targets.HasFlag(StatusEffect.TargetType.Contained)) - effect.Apply(ActionType.OnContaining, deltaTime, item, contained.AllPropertyObjects); + effect.Apply(ActionType.OnContaining, deltaTime, item, contained.AllPropertyObjects); } } @@ -192,7 +192,7 @@ namespace Barotrauma.Items.Components return true; } - return false; + return false; } public override void OnMapLoaded() diff --git a/Barotrauma/BarotraumaShared/Source/Items/Components/Machines/Deconstructor.cs b/Barotrauma/BarotraumaShared/Source/Items/Components/Machines/Deconstructor.cs index 96b285ea4..40ef6463c 100644 --- a/Barotrauma/BarotraumaShared/Source/Items/Components/Machines/Deconstructor.cs +++ b/Barotrauma/BarotraumaShared/Source/Items/Components/Machines/Deconstructor.cs @@ -57,7 +57,8 @@ namespace Barotrauma.Items.Components foreach (DeconstructItem deconstructProduct in targetItem.Prefab.DeconstructItems) { - if (deconstructProduct.RequireFullCondition && targetItem.Condition < targetItem.Prefab.Health) continue; + float percentageHealth = targetItem.Condition / targetItem.Prefab.Health; + if (percentageHealth <= deconstructProduct.MinCondition || percentageHealth > deconstructProduct.MaxCondition) continue; var itemPrefab = MapEntityPrefab.Find(deconstructProduct.ItemPrefabName) as ItemPrefab; if (itemPrefab == null) @@ -69,11 +70,11 @@ namespace Barotrauma.Items.Components //container full, drop the items outside the deconstructor if (containers[1].Inventory.Items.All(i => i != null)) { - Entity.Spawner.AddToSpawnQueue(itemPrefab, item.Position, item.Submarine); + Entity.Spawner.AddToSpawnQueue(itemPrefab, item.Position, item.Submarine, itemPrefab.Health * deconstructProduct.OutCondition); } else { - Entity.Spawner.AddToSpawnQueue(itemPrefab, containers[1].Inventory); + Entity.Spawner.AddToSpawnQueue(itemPrefab, containers[1].Inventory, itemPrefab.Health * deconstructProduct.OutCondition); } } diff --git a/Barotrauma/BarotraumaShared/Source/Items/Components/Machines/Fabricator.cs b/Barotrauma/BarotraumaShared/Source/Items/Components/Machines/Fabricator.cs index 9857fb052..7a1e32758 100644 --- a/Barotrauma/BarotraumaShared/Source/Items/Components/Machines/Fabricator.cs +++ b/Barotrauma/BarotraumaShared/Source/Items/Components/Machines/Fabricator.cs @@ -12,10 +12,12 @@ namespace Barotrauma.Items.Components { public readonly ItemPrefab TargetItem; - public readonly List> RequiredItems; + public readonly List> RequiredItems; public readonly float RequiredTime; + public readonly float OutCondition; //Percentage-based from 0 to 1 + public readonly List RequiredSkills; public FabricableItem(XElement element) @@ -31,8 +33,9 @@ namespace Barotrauma.Items.Components RequiredSkills = new List(); RequiredTime = element.GetAttributeFloat("requiredtime", 1.0f); - RequiredItems = new List>(); - + OutCondition = element.GetAttributeFloat("outcondition", 1.0f); + RequiredItems = new List>(); + //Backwards compatibility for string lists string[] requiredItemNames = element.GetAttributeString("requireditems", "").Split(','); foreach (string requiredItemName in requiredItemNames) { @@ -48,12 +51,12 @@ namespace Barotrauma.Items.Components var existing = RequiredItems.Find(r => r.Item1 == requiredItem); if (existing == null) { - RequiredItems.Add(new Tuple(requiredItem, 1)); + RequiredItems.Add(new Tuple(requiredItem, 1, 1.0f, false)); } else { RequiredItems.Remove(existing); - RequiredItems.Add(new Tuple(requiredItem, existing.Item2 + 1)); + RequiredItems.Add(new Tuple(requiredItem, existing.Item2 + 1, 1.0f, false)); } } @@ -66,6 +69,34 @@ namespace Barotrauma.Items.Components subElement.GetAttributeString("name", ""), subElement.GetAttributeInt("level", 0))); break; + case "item": //New system allowing for setting minimal item condition + string requiredItemName = subElement.GetAttributeString("name", ""); + float minCondition = subElement.GetAttributeFloat("mincondition", 1.0f); + //Substract mincondition from required item's condition or delete it regardless? + bool useCondition = subElement.GetAttributeBool("usecondition", true); + int count = subElement.GetAttributeInt("count", 1); + + if (string.IsNullOrWhiteSpace(requiredItemName)) continue; + + ItemPrefab requiredItem = MapEntityPrefab.Find(requiredItemName.Trim()) as ItemPrefab; + if (requiredItem == null) + { + DebugConsole.ThrowError("Error in fabricable item " + name + "! Required item \"" + requiredItemName + "\" not found."); + continue; + } + + var existing = RequiredItems.Find(r => r.Item1 == requiredItem); + if (existing == null) + { + RequiredItems.Add(new Tuple(requiredItem, count, minCondition, useCondition)); + } + else + { + RequiredItems.Remove(existing); + RequiredItems.Add(new Tuple(requiredItem, existing.Item2 + count, minCondition, useCondition)); + } + + break; } } @@ -236,25 +267,32 @@ namespace Barotrauma.Items.Components return; } - foreach (Tuple ip in fabricatedItem.RequiredItems) + foreach (Tuple ip in fabricatedItem.RequiredItems) { for (int i = 0; i < ip.Item2; i++) { - var requiredItem = containers[0].Inventory.Items.FirstOrDefault(it => it != null && it.Prefab == ip.Item1); + var requiredItem = containers[0].Inventory.Items.FirstOrDefault(it => it != null && it.Prefab == ip.Item1 && it.Condition >= ip.Item1.Health * ip.Item3); if (requiredItem == null) continue; - + + //Item4 = use condition bool + if (ip.Item4 && requiredItem.Condition - ip.Item1.Health * ip.Item3 > 0.0f) //Leave it behind with reduced condition if it has enough to stay above 0 + { + requiredItem.Condition -= ip.Item1.Health * ip.Item3; + continue; + } Entity.Spawner.AddToRemoveQueue(requiredItem); containers[0].Inventory.RemoveItem(requiredItem); } } + //TODO: apply OutCondition if (containers[1].Inventory.Items.All(i => i != null)) { - Entity.Spawner.AddToSpawnQueue(fabricatedItem.TargetItem, item.Position, item.Submarine); + Entity.Spawner.AddToSpawnQueue(fabricatedItem.TargetItem, item.Position, item.Submarine, fabricatedItem.TargetItem.Health * fabricatedItem.OutCondition); } else { - Entity.Spawner.AddToSpawnQueue(fabricatedItem.TargetItem, containers[1].Inventory); + Entity.Spawner.AddToSpawnQueue(fabricatedItem.TargetItem, containers[1].Inventory, fabricatedItem.TargetItem.Health * fabricatedItem.OutCondition); } CancelFabricating(null); @@ -269,11 +307,10 @@ namespace Barotrauma.Items.Components { return false; } - ItemContainer container = item.GetComponent(); - foreach (Tuple ip in fabricableItem.RequiredItems) + foreach (Tuple ip in fabricableItem.RequiredItems) { - if (Array.FindAll(container.Inventory.Items, it => it != null && it.Prefab == ip.Item1).Length < ip.Item2) return false; + if (Array.FindAll(container.Inventory.Items, it => it != null && it.Prefab == ip.Item1 && it.Condition >= ip.Item1.Health * ip.Item3).Length < ip.Item2) return false; } return true; diff --git a/Barotrauma/BarotraumaShared/Source/Items/Components/Wearable.cs b/Barotrauma/BarotraumaShared/Source/Items/Components/Wearable.cs index 168387bc8..41bd2b074 100644 --- a/Barotrauma/BarotraumaShared/Source/Items/Components/Wearable.cs +++ b/Barotrauma/BarotraumaShared/Source/Items/Components/Wearable.cs @@ -10,19 +10,23 @@ namespace Barotrauma.Items.Components class WearableSprite { public readonly Sprite Sprite; + public readonly LimbType Limb; public readonly bool HideLimb; public readonly bool InheritLimbDepth; public readonly LimbType DepthLimb; public readonly Wearable WearableComponent; + public readonly string Sound; - public WearableSprite(Wearable item, Sprite sprite, bool hideLimb, bool inheritLimbDepth = true, LimbType depthLimb = LimbType.None) + public WearableSprite(Wearable item, Sprite sprite, LimbType limb, bool hideLimb, bool inheritLimbDepth = true, LimbType depthLimb = LimbType.None, string sound = null) { WearableComponent = item; Sprite = sprite; + Limb = limb; HideLimb = hideLimb; InheritLimbDepth = inheritLimbDepth; DepthLimb = depthLimb; + Sound = sound; } } @@ -66,15 +70,16 @@ namespace Barotrauma.Items.Components string spritePath = subElement.Attribute("texture").Value; spritePath = Path.GetDirectoryName(item.Prefab.ConfigFile) + "/" + spritePath; + var sound = subElement.GetAttributeString("sound", ""); var sprite = new Sprite(subElement, "", spritePath); - wearableSprites[i] = new WearableSprite(this, sprite, - subElement.GetAttributeBool("hidelimb", false), - subElement.GetAttributeBool("inheritlimbdepth", true), - (LimbType)Enum.Parse(typeof(LimbType), subElement.GetAttributeString("depthlimb", "None"), true)); - limbType[i] = (LimbType)Enum.Parse(typeof(LimbType), subElement.GetAttributeString("limb", "Head"), true); + wearableSprites[i] = new WearableSprite(this, sprite, limbType[i], + subElement.GetAttributeBool("hidelimb", false), + subElement.GetAttributeBool("inheritlimbdepth", true), + (LimbType)Enum.Parse(typeof(LimbType), subElement.GetAttributeString("depthlimb", "None"), true), sound); + i++; break; case "damagemodifier": diff --git a/Barotrauma/BarotraumaShared/Source/Items/Item.cs b/Barotrauma/BarotraumaShared/Source/Items/Item.cs index 398fb96d3..802e5498f 100644 --- a/Barotrauma/BarotraumaShared/Source/Items/Item.cs +++ b/Barotrauma/BarotraumaShared/Source/Items/Item.cs @@ -335,18 +335,18 @@ namespace Barotrauma } } - public Item(ItemPrefab itemPrefab, Vector2 position, Submarine submarine) + public Item(ItemPrefab itemPrefab, Vector2 position, Submarine submarine, float? spawnCondition = null) : this(new Rectangle( (int)(position.X - itemPrefab.sprite.size.X / 2), (int)(position.Y + itemPrefab.sprite.size.Y / 2), (int)itemPrefab.sprite.size.X, (int)itemPrefab.sprite.size.Y), - itemPrefab, submarine) + itemPrefab, submarine, spawnCondition) { } - public Item(Rectangle newRect, ItemPrefab itemPrefab, Submarine submarine) + public Item(Rectangle newRect, ItemPrefab itemPrefab, Submarine submarine, float? spawnCondition = null) : base(itemPrefab, submarine) { prefab = itemPrefab; @@ -361,8 +361,8 @@ namespace Barotrauma rect = newRect; - condition = prefab.Health; - lastSentCondition = prefab.Health; + condition = (float)(spawnCondition ?? prefab.Health); + lastSentCondition = condition; XElement element = prefab.ConfigElement; if (element == null) return; @@ -781,7 +781,7 @@ namespace Barotrauma float surfaceY = CurrentHull.Surface; - return Position.Y < surfaceY; + return CurrentHull.WaterVolume > 0.0f && Position.Y < surfaceY; } @@ -826,44 +826,46 @@ namespace Barotrauma } } - inWater = IsInWater(); - if (inWater) ApplyStatusEffects(ActionType.InWater, deltaTime); - - if (body == null || !body.Enabled) return; - - System.Diagnostics.Debug.Assert(body.FarseerBody.FixtureList != null); - - if (Math.Abs(body.LinearVelocity.X) > 0.01f || Math.Abs(body.LinearVelocity.Y) > 0.01f) + if (body != null && body.Enabled) { - Submarine prevSub = Submarine; + System.Diagnostics.Debug.Assert(body.FarseerBody.FixtureList != null); - FindHull(); + if (Math.Abs(body.LinearVelocity.X) > 0.01f || Math.Abs(body.LinearVelocity.Y) > 0.01f) + { + Submarine prevSub = Submarine; - if (Submarine == null && prevSub != null) - { - body.SetTransform(body.SimPosition + prevSub.SimPosition, body.Rotation); - } - else if (Submarine != null && prevSub == null) - { - body.SetTransform(body.SimPosition - Submarine.SimPosition, body.Rotation); - } - - Vector2 displayPos = ConvertUnits.ToDisplayUnits(body.SimPosition); - rect.X = (int)(displayPos.X - rect.Width / 2.0f); - rect.Y = (int)(displayPos.Y + rect.Height / 2.0f); + FindHull(); - if (Math.Abs(body.LinearVelocity.X) > MaxVel || Math.Abs(body.LinearVelocity.Y) > MaxVel) - { - body.LinearVelocity = new Vector2( - MathHelper.Clamp(body.LinearVelocity.X, -MaxVel, MaxVel), - MathHelper.Clamp(body.LinearVelocity.Y, -MaxVel, MaxVel)); + if (Submarine == null && prevSub != null) + { + body.SetTransform(body.SimPosition + prevSub.SimPosition, body.Rotation); + } + else if (Submarine != null && prevSub == null) + { + body.SetTransform(body.SimPosition - Submarine.SimPosition, body.Rotation); + } + + Vector2 displayPos = ConvertUnits.ToDisplayUnits(body.SimPosition); + rect.X = (int)(displayPos.X - rect.Width / 2.0f); + rect.Y = (int)(displayPos.Y + rect.Height / 2.0f); + + if (Math.Abs(body.LinearVelocity.X) > MaxVel || Math.Abs(body.LinearVelocity.Y) > MaxVel) + { + body.LinearVelocity = new Vector2( + MathHelper.Clamp(body.LinearVelocity.X, -MaxVel, MaxVel), + MathHelper.Clamp(body.LinearVelocity.Y, -MaxVel, MaxVel)); + } } + + UpdateNetPosition(); } - UpdateNetPosition(); - - if (!inWater || ParentInventory != null) return; - + inWater = IsInWater(); + + if (inWater) ApplyStatusEffects(ActionType.InWater, deltaTime); + + if (body == null || !body.Enabled || !inWater || ParentInventory != null) return; + ApplyWaterForces(); CurrentHull?.ApplyFlowForces(deltaTime, this); } @@ -1104,8 +1106,6 @@ namespace Barotrauma ic.ApplyStatusEffects(ActionType.OnPicked, 1.0f, picker); #if CLIENT - ic.PlaySound(ActionType.OnPicked, picker.WorldPosition); - if (picker == Character.Controlled) GUIComponent.ForceMouseOn(null); #endif diff --git a/Barotrauma/BarotraumaShared/Source/Items/ItemPrefab.cs b/Barotrauma/BarotraumaShared/Source/Items/ItemPrefab.cs index dba9dfd98..bf19c6c0a 100644 --- a/Barotrauma/BarotraumaShared/Source/Items/ItemPrefab.cs +++ b/Barotrauma/BarotraumaShared/Source/Items/ItemPrefab.cs @@ -10,12 +10,16 @@ namespace Barotrauma struct DeconstructItem { public readonly string ItemPrefabName; - public readonly bool RequireFullCondition; + public readonly float MinCondition; + public readonly float MaxCondition; + public readonly float OutCondition; - public DeconstructItem(string itemPrefabName, bool requireFullCondition) + public DeconstructItem(string itemPrefabName, float minCondition, float maxCondition, float outCondition) { ItemPrefabName = itemPrefabName; - RequireFullCondition = requireFullCondition; + MinCondition = minCondition; + MaxCondition = maxCondition; + OutCondition = outCondition; } } @@ -301,9 +305,14 @@ namespace Barotrauma { string deconstructItemName = deconstructItem.GetAttributeString("name", "not found"); - bool requireFullCondition = deconstructItem.GetAttributeBool("requirefullcondition", false); + //minCondition does <= check, meaning that below or equeal to min condition will be skipped. + float minCondition = deconstructItem.GetAttributeFloat("mincondition", -0.1f); + //maxCondition does > check, meaning that above this max the deconstruct item will be skipped. + float maxCondition = deconstructItem.GetAttributeFloat("maxcondition", 1.0f); + //Condition of item on creation + float outCondition = deconstructItem.GetAttributeFloat("outcondition", 1.0f); - DeconstructItems.Add(new DeconstructItem(deconstructItemName, requireFullCondition)); + DeconstructItems.Add(new DeconstructItem(deconstructItemName, minCondition, maxCondition, outCondition)); } diff --git a/Barotrauma/BarotraumaShared/Source/Map/Structure.cs b/Barotrauma/BarotraumaShared/Source/Map/Structure.cs index 9e6e630cd..a0865ede5 100644 --- a/Barotrauma/BarotraumaShared/Source/Map/Structure.cs +++ b/Barotrauma/BarotraumaShared/Source/Map/Structure.cs @@ -518,7 +518,7 @@ namespace Barotrauma float impact = Vector2.Dot(f2.Body.LinearVelocity, -normal)*f2.Body.Mass*0.1f; #if CLIENT - SoundPlayer.PlayDamageSound(DamageSoundType.StructureBlunt, impact, + SoundPlayer.PlayDamageSound("StructureBlunt", impact, new Vector2( sections[section].rect.X + sections[section].rect.Width / 2, sections[section].rect.Y - sections[section].rect.Height / 2), tags: Tags); @@ -679,7 +679,7 @@ namespace Barotrauma #if CLIENT if (playSound)// && !SectionBodyDisabled(i)) { - DamageSoundType damageSoundType = (attack.DamageType == DamageType.Blunt) ? DamageSoundType.StructureBlunt : DamageSoundType.StructureSlash; + string damageSoundType = (attack.DamageType == DamageType.Blunt) ? "StructureBlunt" : "StructureSlash"; SoundPlayer.PlayDamageSound(damageSoundType, damageAmount, worldPosition, tags: Tags); } #endif diff --git a/Barotrauma/BarotraumaShared/Source/Map/SubmarineBody.cs b/Barotrauma/BarotraumaShared/Source/Map/SubmarineBody.cs index 783dcce34..0aee7abd1 100644 --- a/Barotrauma/BarotraumaShared/Source/Map/SubmarineBody.cs +++ b/Barotrauma/BarotraumaShared/Source/Map/SubmarineBody.cs @@ -681,7 +681,7 @@ namespace Barotrauma if (maxDamageStructure != null) { SoundPlayer.PlayDamageSound( - DamageSoundType.StructureBlunt, + "StructureBlunt", impact * 10.0f, ConvertUnits.ToDisplayUnits(lastContactPoint), MathHelper.Clamp(maxDamage * 4.0f, 1000.0f, 4000.0f), diff --git a/Barotrauma/BarotraumaShared/Source/Networking/EntitySpawner.cs b/Barotrauma/BarotraumaShared/Source/Networking/EntitySpawner.cs index 3ad1322c8..448cbd819 100644 --- a/Barotrauma/BarotraumaShared/Source/Networking/EntitySpawner.cs +++ b/Barotrauma/BarotraumaShared/Source/Networking/EntitySpawner.cs @@ -22,24 +22,28 @@ namespace Barotrauma public readonly Vector2 Position; public readonly Inventory Inventory; public readonly Submarine Submarine; + public readonly float Condition; - public ItemSpawnInfo(ItemPrefab prefab, Vector2 worldPosition) + public ItemSpawnInfo(ItemPrefab prefab, Vector2 worldPosition, float? condition = null) { Prefab = prefab; Position = worldPosition; + Condition = (float)(condition ?? prefab.Health); } - public ItemSpawnInfo(ItemPrefab prefab, Vector2 position, Submarine sub) + public ItemSpawnInfo(ItemPrefab prefab, Vector2 position, Submarine sub, float? condition = null) { Prefab = prefab; Position = position; Submarine = sub; + Condition = (float)(condition ?? prefab.Health); } - public ItemSpawnInfo(ItemPrefab prefab, Inventory inventory) + public ItemSpawnInfo(ItemPrefab prefab, Inventory inventory, float? condition = null) { Prefab = prefab; Inventory = inventory; + Condition = (float)(condition ?? prefab.Health); } public Entity Spawn() @@ -48,12 +52,12 @@ namespace Barotrauma if (Inventory != null) { - spawnedItem = new Item(Prefab, Vector2.Zero, null); + spawnedItem = new Item(Prefab, Vector2.Zero, null, Condition); Inventory.TryPutItem(spawnedItem, null, spawnedItem.AllowedSlots); } else { - spawnedItem = new Item(Prefab, Position, Submarine); + spawnedItem = new Item(Prefab, Position, Submarine, Condition); } return spawnedItem; @@ -83,25 +87,25 @@ namespace Barotrauma removeQueue = new Queue(); } - public void AddToSpawnQueue(ItemPrefab itemPrefab, Vector2 worldPosition) + public void AddToSpawnQueue(ItemPrefab itemPrefab, Vector2 worldPosition, float? condition = null) { if (GameMain.Client != null) return; - spawnQueue.Enqueue(new ItemSpawnInfo(itemPrefab, worldPosition)); + spawnQueue.Enqueue(new ItemSpawnInfo(itemPrefab, worldPosition, condition)); } - public void AddToSpawnQueue(ItemPrefab itemPrefab, Vector2 position, Submarine sub) + public void AddToSpawnQueue(ItemPrefab itemPrefab, Vector2 position, Submarine sub, float? condition = null) { if (GameMain.Client != null) return; - spawnQueue.Enqueue(new ItemSpawnInfo(itemPrefab, position, sub)); + spawnQueue.Enqueue(new ItemSpawnInfo(itemPrefab, position, sub, condition)); } - public void AddToSpawnQueue(ItemPrefab itemPrefab, Inventory inventory) + public void AddToSpawnQueue(ItemPrefab itemPrefab, Inventory inventory, float? condition = null) { if (GameMain.Client != null) return; - spawnQueue.Enqueue(new ItemSpawnInfo(itemPrefab, inventory)); + spawnQueue.Enqueue(new ItemSpawnInfo(itemPrefab, inventory, condition)); } public void AddToRemoveQueue(Entity entity) diff --git a/Barotrauma/BarotraumaShared/Source/Networking/GameServer.cs b/Barotrauma/BarotraumaShared/Source/Networking/GameServer.cs index 9094b43bc..4d7ebcc4b 100644 --- a/Barotrauma/BarotraumaShared/Source/Networking/GameServer.cs +++ b/Barotrauma/BarotraumaShared/Source/Networking/GameServer.cs @@ -1509,7 +1509,9 @@ namespace Barotrauma.Networking yield return CoroutineStatus.Running; } while (cinematic.Running);//(secondsLeft > 0.0f); - +#if CLIENT + SoundPlayer.OverrideMusicType = null; +#endif Submarine.Unload(); entityEventManager.Clear();